问题描述
- 问一个笼统的问题,ios客户端和服务器通信都有什么方法
- ios客户端和服务器通信时
都有那些方法?那种比较好用或最常用的?
解决方案
ios设备的网络通信的方法,有如下两个大类:
1、使用socket的方式进行通信。
2、使用asynsocket类库进行通信。
两种方法当中,我觉得asynsocket更好,因为是别人已经封装好的类库,比较稳定。但是对于直接使用socket的通信方法我倒是觉得很灵活。因为控制都是自己在做的事情。
先列举集中不同的使用方法:
1、直接使用socket的方式。
以 TCP为利,对于TCP来说,是要区分服务端和客户端的。服务端:通常的方法是服务端启动后监听,是否有客户端连接,如果有连接,则建立与客户端的通信。客户端的方法通常是连接服务端,当连接成功之后,就希望发送数据了。
客户端:
CFSocketContext sockContext ;
CFSocketRef cfsock ;
sockContext.info = self;
sockContext.copyDescription = 0;
cfsock = CFSocketCreate(kCFAllocatorDefault
PF_INET
SOCK_STREAM
IPPROTO_TCP
kCFSocketConnectCallBack
MyCallBack
&sockContext
);
// 这个地方是个关键的地方,就是建立一个ip地址,然后使的客户端可以向服务端发起连接。
NSString *strAddress = @""192.168.1.1"";
if (cfsock != nil) {
struct sockaddr_in addr4;
memset(&addr40sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(1230);
addr4.sin_addr.s_addr = inet_addr( [strAddress UTF8String] );
CFDataRef address = CFDataCreate(kCFAllocatorDefault (UInt8*)&addr4 sizeof(addr4));
CFSocketConnectToAddress(cfsock address -1);
}
// 发起连接之后,需要将runloop的过程,也就是消息的过程加入到当前线程当中。这样当有事件发生时,会调用对应的方法。
CFRunLoopRef crun = CFRunLoopGetCurrent();// CFRunLoopGetMain();
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault cfsock 0);
CFRunLoopAddSource(crun source kCFRunLoopCommonModes);
CFRelease(source);
回调函数:当连接成功之后的处理如下:
static void MyCallBack (
CFSocketRef s
CFSocketCallBackType callbackType
CFDataRef address
const void *data
void *info
)
{
if (data!=NULL) {
NSLog(@""传输失败!"");
}
SocketTestAppDelegate client = (SocketTestAppDelegate)info;
[client performSelectoInBackground:@selector(readstream) withObject:nil];
}
-(void) readstream
{
char buffer[1024];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (recv(CFSocketGetNative(cfsock)buffersizeof(buffer)0)) {
}
[pool release];
}
// 如果希望直接向服务器写内容的话,采用如下的方法。
-(void) sendstream
{
NSString * stringtosend = @""hello everyone"";
const char *data = [stringtosend UTF8String];
send(CFSocketGetNative(cfsock)datastrlen(data)+10);
}
服务器端的程序:
CFSocketRef socketserver;
int setupSocket()
{
socketserver =CFSocketCreate(kCFAllocatorDefaultPF_INETSOCK_STREAMIPPROTO_TCPkCFSocketAcceptCallBackmyacceptNULL);
int optval =1;
setsockopt(CFSocketGetNative(socketserver) SOL_SOCKET SO_REUSEADDR (void*)&optvalsizeof(optval));
struct sockaddr_in addr4;
memset(&addr40sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(10);
addr4.sin_addr.s_addr=htonl(INADDR_ANY);
CFDataRef address = CFDataCreate(kCFAllocatorDefault (UInt8*)&addr4 sizeof(addr4));
CFSocketSetAddress(socketserver address);
CFRunLoopRef cfRunloop = CFRunLoopGetCurrent();
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault socketserver 0);
CFRunLoopAddSource(cfRunloop source kCFRunLoopCommonModes);
CFRelease(source);
}
//服务端的socket建立之后,就需要接受client的连接,因此建立连接的回调函数。
static void myaccept (
CFSocketRef s
CFSocketCallBackType callbackType
CFDataRef address
const void *data
void *info
)
{
if (callbackType == kCFSocketAcceptCallBack) {
// 如果对端连接成功的话,是可以获取对端的名称和socket的。
CFSocketNativeHandle nativesockethandle = (CFSocketNativeHandle)data;
uint8_t name[100];
socklen_t namelen = 100;
getpeername(nativesockethandle (struct sockaddr *)name &namelen);
//除此以外,更重要的是获取输入流 和 输出流,
CFReadStreamRef iStream;
CFWriteStreamRef oStream;
// 创建一个可读写的socket连接
CFStreamCreatePairWithSocket(kCFAllocatorDefault nativesockethandle &iStream &oStream);
CFStreamClientContext streamcontext={
0NULLNULLNULL
};
// 注册两种事件!
CFReadStreamSetClient(iStream kCFStreamEventHasBytesAvailable readStream &streamcontext);
CFReadStreamSetClient(iStream kCFStreamEventCanAcceptBytes writeStream &streamcontext);
//加入到循环当中!
CFReadStreamScheduleWithRunLoop(iStream CFRunLoopGetCurrent()kCFRunLoopCommonModes);
CFWriteStreamScheduleWithRunLoop(oStream CFRunLoopGetCurrent()kCFRunLoopCommonModes);
CFReadStreamOpen(iStream);
CFWriteStreamOpen(oStream);
}
}
void readStream(CFReadStreamRef streamCFStreamEventType eventType void *clientCallBackInfo) {
UInt8 buff[255];CFReadStreamRead(stream buff 255);printf(""received: %s"" buff);
}
void writeStream (CFWriteStreamRef stream CFStreamEventType eventType void *clientCallBackInfo) {
// outputStream = stream;
char *str = ""nihao"";
CFWriteStreamWrite(outputStream str strlen(line) + 1);
}
另一种方法是使用NSStream的方式构建客户端,然后发送和接受内容。
-(void)startClient
{
host
= [NSHosthostWithAddress:@""192.168.201.24""];//hostWithName:@""www.apple.com""];
[NSStreamgetStreamsToHost:host
port:4242 inputStream:&inStream outputStream:&outStream];
if((inStream
== nil)
|| (outStream == nil))
{ NSLog(@""Error:
Failed to create streams!"")
;
[selfrelease];}
}
(void)stream:(NSStream*)aStream
handleEvent:(NSStreamEvent)eventCode
{
switch(eventCode)
{
caseNSStreamEventHasBytesAvailable: { NSMutableData*input
= [[NSMutableDataalloc]
init];
uint8_t
buffer[1024];
intlen; while([inStream
hasBytesAvailable])
{ len
= [inStream read:buffer maxLength:sizeof(buffer)];
if(len
0)
{ [input
appendBytes:buffer length:len];
} } self._resultdata
= input;
self._resultstring
= [[NSStringalloc]
initWithData:input encoding:NSUTF8StringEncoding];
[input
release];
break; } caseNSStreamEventEndEncountered: [selfcloseStream]; break; caseNSStreamEventHasSpaceAvailable: caseNSStreamEventErrorOccurred: { NSLog(@""Error:%@:%@""[[aStream
streamError] code] [[aStream streamError] localizedDescription]);
} caseNSStreamEventOpenCompleted: caseNSStreamEventNone: default: break;}
}
-(void)closeStream{
[inStream
close];
[outStream
close];
[inStream
removeFromRunLoop:[NSRunLoopcurrentRunLoop]
forMode:NSDefaultRunLoopMode];
[outStream
removeFromRunLoop:[NSRunLoopcurrentRunLoop]
forMode:NSDefaultRunLoopMode];
[inStream
setDelegate:nil];
[outStream
setDelegate:nil];
[inStream
release];
[outStream
release];
inStream
= nil;
outStream
= nil;
}
-(void)openStream{
[inStream
retain];
[outStream
retain];
[inStream
setProperty:NSStreamSocketSecurityLevelSSLv3forKey:NSStreamSocketSecurityLevelKey];
[outStream
setProperty:NSStreamSocketSecurityLevelSSLv3forKey:NSStreamSocketSecurityLevelKey];
NSMutableDictionary*
sslSettings;
sslSettings
= [NSMutableDictionarydictionaryWithObjectsAndKeys:(id)kCFBooleanFalsekCFStreamSSLValidatesCertificateChainkCFBooleanFalsekCFStreamSSLIsServernil];
CFWriteStreamSetProperty((CFWriteStreamRef)outStream
kCFStreamPropertySSLSettings sslSettings);
[inStream
setDelegate:self];
[outStream
setDelegate:self];
[inStream
scheduleInRunLoop:[NSRunLoopcurrentRunLoop]
forMode:NSDefaultRunLoopMode];
[outStream
scheduleInRunLoop:[NSRunLoopcurrentRunLoop]
forMode:NSDefaultRunLoopMode];
[inStream
open];
[outStream
open];
}
-(int)writeString:
(NSString*)
string
{
NSData*messageAsData
= [string dataUsingEncoding:NSASCIIStringEncoding];
return[outStream
write: (c*****t uint8_t *) [messageAsData bytes] maxLength: [messageAsData length]];
}
-(int)writeBytes:
(char*)
buffer length: (unsigned int)
len
{
return[outStream
write: (c*****t uint8_t *) buffer maxLength: len];
}
@end
转自:http://blog.csdn.net/dongdongdongjl/article/details/7776377
解决方案二:
来一个笼统的回答,通过网络。
解决方案三:
看你时是否需要实时通讯
获取数据提交数据可以直接调用html、webservice
被动接受可以用推送
如果是聊天复杂些,可以看看xmpp