UDP組播 socket

相關(guān)概念:

單播、多播(組播)和廣播的區(qū)別? http://blog.csdn.net/wangerge/article/details/3931491

多播(組播)地址范圍--224.0.0.0到239.255.255.255

廣播地址: 255.255.255.255

應(yīng)用場景:

家庭局域網(wǎng)設(shè)備組件一個局域網(wǎng),各設(shè)備提供udp socket監(jiān)聽服務(wù),手機(jī)客戶端進(jìn)入此局域網(wǎng),并向局域網(wǎng)內(nèi)發(fā)送組播或廣播,對應(yīng)設(shè)備響應(yīng)組播并按需要與手機(jī)端建立tcp長連接通信

1.服務(wù)端:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification

{

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]; //開始接收數(shù)據(jù),一定要否則后面無法接收數(shù)據(jù) 不接收數(shù)據(jù)時調(diào)用pauseReceiving

if (receiveError) {

NSLog(@"receiveError = %@",receiveError);

}

//[serverSocket joinMulticastGroup:@"224.0.1.23" error:nil];//該socket加入到組播224.0.1.23中,之后只要客戶端socket向這個組播地址發(fā)消息,該socket都能收到 與客戶端的發(fā)送地址必須一致才能接收

NSLog(@"%@",[serverSocket localHost]);

///////////////////////////服務(wù)開啟時同時開啟TCP服務(wù)監(jiān)聽,以便后面建立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)聽端口必須要與udp socket的端口一樣 后面客戶端才能正確與服務(wù)端建立tcp連接,因為客戶端到時獲取的端口是udp socket的端口

{

NSLog(@"err.description = %@",err.description);

}else

{

NSLog(@"%@",[NSString stringWithFormat:@"開始監(jiān)聽%d端口.",8099]);

}

/////////////////////////////

}

udpsocket的關(guān)鍵回調(diào)方法:接收到客戶端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];//可獲取客戶端socket的ip和端口,不過直接打印address是空的

NSLog(@"Adress = %@ %i",host,port);

[sock sendData:[responseMessage dataUsingEncoding:NSUTF8StringEncoding] toAddress:address withTimeout:-1 tag:10];//服務(wù)端回應(yīng)客戶端

}

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.客戶端:

- (IBAction)broadCast:(id)sender {

GCDAsyncUdpSocket *udpSocket = [[[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()] autorelease];

NSError *error = nil;

[udpSocket enableBroadcast:YES error:&error];//允許廣播 必須 否則后面無法發(fā)送組播和廣播

NSString *message = @"ttt";

//[udpSocket sendData:[message dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:10];//該函數(shù)只能用戶已經(jīng)連接的socket

[udpSocket sendData:[message dataUsingEncoding:NSUTF8StringEncoding] toHost:@"224.0.1.23"? port:8099 withTimeout:-1 tag:10];//客戶端socket發(fā)送組播或是廣播 根據(jù)host的ip地址來訂

[udpSocket beginReceiving:nil];//必須要? 開始準(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);

//開啟tcp連接

sockeTCP = [[GCDAsyncSocket alloc]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);

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容