守望远方

热爱生活 热爱工作 守望远方
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(&addr4,0,sizeof(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(kCFAllocatorDefaultcfsock0);

 

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(readstreamwithObject:nil];

 

 

}

 

-(void) readstream

{

char buffer[1024];

 

NSAutoreleasePool *pool = [[NSAutoreleasePool allocinit];

 

while (recv(CFSocketGetNative(cfsock),buffer,sizeof(buffer),0)) {

 

}

 

[pool release];

}

//  如果希望直接向服务器写内容的话,采用如下的方法。

-(void) sendstream

{

NSString * stringtosend = @"hello everyone";

 

const char *data = [stringtosend UTF8String];

 

send(CFSocketGetNative(cfsock),data,strlen(data)+1,0);

}

 

服务器端的程序:

 

 

CFSocketRef socketserver;

int setupSocket()

{

socketserver =CFSocketCreate(kCFAllocatorDefault,PF_INET,SOCK_STREAM,IPPROTO_TCP,kCFSocketAcceptCallBack,myaccept,NULL);

 

int optval =1;

 

setsockopt(CFSocketGetNative(socketserver), SOL_SOCKETSO_REUSEADDR, (void*)&optval,sizeof(optval));

 

struct sockaddr_in addr4;

 

memset(&addr4,0,sizeof(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(kCFAllocatorDefaultsocketserver0);

 

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={

0,NULL,NULL,NULL

};

// 注册两种事件!

 

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 stream,CFStreamEventType 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)kCFBooleanFalse,kCFStreamSSLValidatesCertificateChain,kCFBooleanFalse,kCFStreamSSLIsServer,nil];
    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

posted on 2012-12-24 11:54  守望远方  阅读(441)  评论(0编辑  收藏  举报