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(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),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_SOCKET, SO_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(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={

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 = [ NSHost hostWithAddress:@ "192.168.201.24" ]; //hostWithName:@"www.apple.com"];
     [ NSStream getStreamsToHost:host port:4242 inputStream:&inStream outputStream:&outStream];
     
     if ((inStream == nil ) || (outStream == nil ))
     {
         NSLog (@ "Error: Failed to create streams!" ) ;
         [ self release];
     }
}
 
- ( void )stream:( NSStream *)aStream handleEvent:( NSStreamEvent )eventCode
{
     switch (eventCode) {
         case NSStreamEventHasBytesAvailable :
         {
             NSMutableData *input = [[ NSMutableData alloc] init];
             uint8_t buffer[1024];
             int len;
             while([inStream hasBytesAvailable])
             {
                 len = [inStream read:buffer maxLength: sizeof (buffer)];
                 if (len > 0)
                 {
                     [input appendBytes:buffer length:len];
                 }
             }
             self ._resultdata = input;
             self ._resultstring = [[ NSString alloc] initWithData:input encoding: NSUTF8StringEncoding ];
             [input release];
             break ;
         }
         case NSStreamEventEndEncountered :
             [ self closeStream];
             break ;
         case NSStreamEventHasSpaceAvailable :
         case NSStreamEventErrorOccurred :
         {
             NSLog (@ "Error:%@:%@" ,[[aStream streamError] code], [[aStream streamError] localizedDescription]);
         }
         case NSStreamEventOpenCompleted :
         case NSStreamEventNone :
         default :
             break ;
     }
}
 
-( void )closeStream{
     [inStream close];
     [outStream close];
     [inStream removeFromRunLoop:[ NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode ];
     [outStream removeFromRunLoop:[ NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode ];
     [inStream setDelegate: nil ];
     [outStream setDelegate: nil ];
     [inStream release];
     [outStream release];
     inStream = nil ;
     outStream = nil ;
}
 
-( void )openStream{
     [inStream retain];
     [outStream retain];
     [inStream setProperty: NSStreamSocketSecurityLevelSSLv3 forKey: NSStreamSocketSecurityLevelKey ];
     [outStream setProperty: NSStreamSocketSecurityLevelSSLv3 forKey: NSStreamSocketSecurityLevelKey ];
     NSMutableDictionary * sslSettings;
     sslSettings = [ NSMutableDictionary dictionaryWithObjectsAndKeys:( id )kCFBooleanFalse,kCFStreamSSLValidatesCertificateChain,kCFBooleanFalse,kCFStreamSSLIsServer, nil ];
     CFWriteStreamSetProperty((CFWriteStreamRef)outStream, kCFStreamPropertySSLSettings, sslSettings);
     [inStream setDelegate: self ];
     [outStream setDelegate: self ];
     [inStream scheduleInRunLoop:[ NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode ];
     [outStream scheduleInRunLoop:[ NSRunLoop currentRunLoop] 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





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值