先UDP組播 socket 再TCP建立長(zhǎng)連接
同一個(gè)局域網(wǎng)下,各設(shè)備提供udp socket監(jiān)聽(tīng)服務(wù)禁炒,手機(jī)客戶(hù)端進(jìn)入此局域網(wǎng)而咆,并向局域網(wǎng)內(nèi)發(fā)送組播或廣播,對(duì)應(yīng)設(shè)備響應(yīng)組播并按需要與手機(jī)端建立tcp長(zhǎng)連接通信
1.服務(wù)端
-(void)server{
GCDAsyncUdpSocket *serverSocket = [[[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()] autorelease];
NSError *bindError = nil;
//bindToPort綁定端口函數(shù)幕袱,只能使用在充當(dāng)server 的socket上 client socket不能使用
//[serverSocket bindToPort:8099 interface:@"en1" error:&bindError]; //en1 隨機(jī)分配的ip地址
[serverSocket bindToPort:8099 error:&bindError];//該socket默認(rèn)綁定到該機(jī)子網(wǎng)卡的ip地址
if (bindError) {
NSLog(@"bindError = %@",bindError);
}
NSError *receiveError = nil;
[serverSocket beginReceiving:&receiveError];//開(kāi)始接收數(shù)據(jù)暴备,一定要否則后面無(wú)法接收數(shù)據(jù) 不接收數(shù)據(jù)時(shí)調(diào)用pauseReceiving
if (receiveError) {
NSLog(@"receiveError = %@",receiveError);
}
//[serverSocket joinMulticastGroup:@"224.0.1.23" error:nil];//該socket加入到組播224.0.1.23中,之后只要客戶(hù)端socket向這個(gè)組播地址發(fā)消息们豌,該socket都能收到 與客戶(hù)端的發(fā)送地址必須一致才能接收
NSLog(@"%@",[serverSocket localHost]);
///////////////////////////服務(wù)開(kāi)啟時(shí)同時(shí)開(kāi)啟TCP服務(wù)監(jiān)聽(tīng)涯捻,以便后面建立TCP連接
GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if(![socket acceptOnPort:8099 error:&err])//tcp socket的監(jiān)聽(tīng)端口必須要與udp socket的端口一樣 后面客戶(hù)端才能正確與服務(wù)端建立tcp連接,因?yàn)榭蛻?hù)端到時(shí)獲取的端口是udp socket的端口
{
NSLog(@"err.description = %@",err.description);
}else
{
NSLog(@"%@",[NSString stringWithFormat:@"開(kāi)始監(jiān)聽(tīng)%d端口.",8099]);
}
}
//udpsocket的關(guān)鍵回調(diào)方法:接收到客戶(hù)端socket發(fā)送的消息響應(yīng)如下
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext {
NSLog(@"sock = %@, ReceiveData = %@, fromAddress = %@",sock,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding],[[NSString alloc] initWithData:address encoding:NSUTF8StringEncoding]);
NSString *responseMessage = @"已即受到";
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];//可獲取客戶(hù)端socket的ip和端口望迎,不過(guò)直接打印address是空的
NSLog(@"Adress = %@ %i",host,port);
[sock sendData:[responseMessage dataUsingEncoding:NSUTF8StringEncoding] toAddress:address withTimeout:-1 tag:10];//服務(wù)端回應(yīng)客戶(hù)端
}
//Tcp socket關(guān)鍵回調(diào)方法
- (void)socket:(GCDAsyncSocket *)sender didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
NSLog(@"%@",[NSString stringWithFormat:@"建立與%@的連接",newSocket.connectedHost]);
s = newSocket;
s.delegate = self;
[s readDataWithTimeout:-1 tag:0];//必須調(diào)用
}
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *receive = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",[NSString stringWithFormat:@"%@:%@",sock.connectedHost,receive]);
NSString *reply = [NSString stringWithFormat:@"收到:%@",receive];
[s writeData:[reply dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
[s readDataWithTimeout:-1 tag:0];
}
//2.客戶(hù)端:
- (IBAction)broadCast:(id)sender {
GCDAsyncUdpSocket *udpSocket = [[[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()] autorelease];
NSError *error = nil;
[udpSocket enableBroadcast:YES error:&error];//允許廣播 必須 否則后面無(wú)法發(fā)送組播和廣播
NSString *message = @"ttt";
//[udpSocket sendData:[message dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:10];//該函數(shù)只能用戶(hù)已經(jīng)連接的socket
[udpSocket sendData:[message dataUsingEncoding:NSUTF8StringEncoding] toHost:@"224.0.1.23"port:8099 withTimeout:-1 tag:10];//客戶(hù)端socket發(fā)送組播或是廣播 根據(jù)host的ip地址來(lái)訂
[udpSocket beginReceiving:nil];//必須要開(kāi)始準(zhǔn)備接收數(shù)據(jù)
}
//UDP 回調(diào)函數(shù)
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext{
NSLog(@"ReceiveData = %@, fromAddress = %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding],[[NSString alloc] initWithData:address encoding:NSUTF8StringEncoding]);
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];//從此可以獲取服務(wù)端回應(yīng)的ip和端口 用于后面的tcp連接
NSLog(@"Adress = %@ %i",host,port);
//開(kāi)啟tcp連接
sockeTCP = [[GCDAsyncSocketalloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
//socket.delegate = self;
NSError *err = nil;
if(![sockeTCP connectToHost:host onPort:port error:&err])
{
}else
{
NSLog(@"tcp ok");
[sockeTCP writeData:[@"發(fā)送tcp消息" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
[sockeTCP readDataWithTimeout:-1 tag:0];
}
}
//TCP 回調(diào)函數(shù):
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
NSLog(@"%@",[NSString stringWithFormat:@"tcp連接到:%@",host]);
[sockeTCP readDataWithTimeout:-1 tag:0];
}
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *newMessage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"tcp newMessage = %@",newMessage);
}