最近工作中使用别人的SDK时看到了AsyncSocket这个类 简单查看了这个类的用处,发现是iOS socket套接字的封装 用于iOS的socket编程,上学时曾学到Linux的socket编程都是C函数,上学时不用功(惭愧),对socket算是听说过,于是有些兴趣再学习学习。
我使用socket编程 用到的通信协议有TCP和UDP。 TCP是可传输控制协议,它的传输是可靠的,需要三次握手建立连接, 四次握手释放链接(具体怎么过程就不多说了),UDP是用户数据报协议 传输是不可靠地。
下载AsyncSockethttps://github.com/robbiehanson/CocoaAsyncSocket类库,将RunLoop文件夹下的AsyncSocket.h, AsyncSocket.m, AsyncUdpSocket.h, AsyncUdpSocket.m 文件拷贝到自己的project中
添加CFNetwork.framework, 在使用socket的文件头
一、UDP:
AsyncUdpSocket类是支持UDP协议的socket编程类,使用也很容易,通信的收发过程都有代理可以调用。
self.udpSocket =[[AsyncUdpSocket alloc]initWithDelegate:self];//初始化socket,设置代理为self
self.portTF.text = @"8888";
NSError *error;
[self.udpSocket enableBroadcast:YES error:&error];//设置允许socket广播,如果不设置,则不能发消息
BOOL isBind = [self.udpSocket bindToPort:[self.portTF.text intValue] error:&error];//绑定一个未用的端口,我设置的是8888 初始化一个socket只能绑定一次,多次绑定直接崩 重新绑定得先调用[self.udpSocket close];然后重新生成一个socket再绑定。
接收数据:
[self.udpSocket receiveWithTimeout:-1 tag:0];//接收数据的方法,调用一次就只接受一次发送的数据包,设置timeout为-1就是永不超时 只要向该socket发送数据就能接收到,接收到数据后会调用- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port 这个代理方法,所接受的数据也在该代理方法的data参数里, 上面接受方法里设置的tag值是几,这代理方法的接收到tag值就是几。host就是发消息的那个socket的主机地址。port是上面绑定的端口号(即8888,也是发送消息的socket的端口号)。
这里如果设置的timeout不是-1,当时间到后超时会调用代理-(void)onUdpSocket:(AsyncUdpSocket *)sock didNotReceiveDataWithTag:(long)tag dueToError:(NSError *)error
发送数据:
NSString *str = self.sendTFV.text;
NSData *data=[str dataUsingEncoding:NSUTF8StringEncoding];
[self.udpSocket sendData:data toHost:self.serverHost port:[self.portTF.text intValue] withTimeout:5 tag:0];//这是发送的方法 发送完后会调用代理-(void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag 这里的tag值与发送时设置的tag一致
这里自己测试时写了自己的小程序玩玩socket udp通信程序 链接: https://pan.baidu.com/s/1SxpfWDq9yCOxELpegr_Jtg 提取码: yq8q
demo里有一个server程序、一个client程序。一个server程序可以用来广播搜索同一网段内的client设备,玩的时候可以找三台设备(我用的是一个iPad,两个iPod,iPad装server程序,两个iPod装client程序,iPad广播搜索后会将两个iPod的IP显示出来,在iPad上选择一/两个IP 发送数据,相应的一/两个iPod会收到数据)。
二、TCP
实现tcp协议需要一个服务器一个客户端,他们之间发送消息时需要先建立一个连接,然后才能收发数据。使用的类AsyncScoket。
服务器端:
self.tcpScoket = [[AsyncSocket alloc]initWithDelegate:self];//初始化 设置代理
NSError *error;
[self.tcpScoket acceptOnPort:8888 error:&error];//这个方法是监听8888端口号,接收通过8888端口号发来的连接请求。收到连接后会走代理- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket 在这个代理方法里 需要使用一个数组保存连接的socket,保证此链接是长连接,如果不保存,则连接完后就会自动断开,从而导致无法互相发收消息;例如(我的demo里):在该方法中使用[self.clientSocketMuArr addObject:newSocket];保存此socket。使用[newSocket readDataWithTimeout:-1 tag:0];接收接下来客户端可能发送的消息。
接下来会走代理方法:-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 该方法中host就是连接的客户端的IP
发送数据:
NSData *data = [self.responseTF.text dataUsingEncoding:NSUTF8StringEncoding];
[self.tcpScoket writeData:data withTimeout:-1 tag:0];这个是发送数据的方法,与udp的发送方法名是不同的,但其功能与UDP的类似,一次只发一个数据。timeout设为-1也是永不超时 调用完之后也有代理方法触发-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
接收数据:
[sock readDataWithTimeout:-1 tag:0];方法名与UDP不同功能上也是类似的 一次只接受一个数据,不调用就不会收到消息,调用之后触发代理- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
客户端:
同样的self.tcpScoket = [[AsyncSocket alloc]initWithDelegate:self];//初始化 设置代理
NSError *error;
BOOL isConnect = [self.tcpScoket connectToHost:@“192.168.3.105” onPort:8888 withTimeout:-1 error:&error];连接服务器,这里的host是服务器的IP,就是你作为服务器的那台设备的IP地址(可以在设置连接WiFi的那里看到),端口号8888就是服务器监听的端口号,注意这里返回的bool值isConnect只是说是否能调用此方法,具体是否连接上服务器要看是否调用代理-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port连接成功后就可以使用[self.tcpScoket writeData:data withTimeout:-1 tag:0];方法向服务器发数据了,收发消息的方法与上面服务器的相同,所触发的代理一是一样的。
这里自己写了小程序socket tcp通信程序 链接: https://pan.baidu.com/s/1bI1gy6 密码: 8tjv demo里有一个server,一个client.