建立網(wǎng)絡(luò)通信連接至少要一對端口號(socket)碎浇。socket本質(zhì)是編程接口(API)讥裤,對TCP/IP的封裝宅静,TCP/IP也要提供可供程序員做網(wǎng)絡(luò)開發(fā)所用的接口,這就是Socket編程接口涌乳;HTTP是轎車蜻懦,提供了封裝或者顯示數(shù)據(jù)的具體形式;Socket是發(fā)動機(jī),提供了網(wǎng)絡(luò)通信的能力夕晓。
http://www.cnblogs.com/purpleraintear/p/6403053.html 這里有一篇關(guān)于UDP疑難雜癥
創(chuàng)建 socket
// 創(chuàng)建 socket
// AF_INET IPv4; AF_INET6 IPv6
// SOCK_STREAM TCP; SOCK_DGRAM UDP
_socketFileDescriptor = socket(AF_INET, SOCK_DGRAM, 0);
發(fā)送廣播
發(fā)送廣播的時候宛乃,需要將socket設(shè)置為廣播:
// 設(shè)置socket的屬性為廣播
int value = 1;
int error = setsockopt(_socketFileDescriptor, SOL_SOCKET, SO_BROADCAST, (const void *)&value, sizeof(value));
發(fā)送廣播數(shù)據(jù):
dispatch_queue_t queue = dispatch_queue_create("net.qigge.socket", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 設(shè)置sendto 發(fā)送的地址
struct sockaddr_in socketParameters;
socketParameters.sin_family = AF_INET;
socketParameters.sin_addr.s_addr = INADDR_BROADCAST;
socketParameters.sin_port = htons([_port intValue]);
sendto(_socketFileDescriptor, [data bytes], [data length], 0, (struct sockaddr *)&socketParameters22, sizeof(struct sockaddr));
NSLog(@"sendto fail, errno=%d\n", errno); // errno 錯誤代碼
});
注意:當(dāng)socket為阻塞模式時,sendto()和recvfrom()將會阻塞當(dāng)前線程蒸辆,應(yīng)當(dāng)將這個兩個方法放入子線程中烤惊。
接收廣播
接收廣播之前,需要先綁定端口:
struct sockaddr_in socketParameters;
socketParameters.sin_family = AF_INET;
socketParameters.sin_addr.s_addr = htonl(INADDR_ANY);
socketParameters.sin_port = htons([_port intValue]);
int b = bind(_socketFileDescriptor, (struct sockaddr *)&socketParameters, sizeof(socketParameters));
if ( b < 0) {
NSLog(@"服務(wù)端綁定失敗");
return;
}
NSLog(@"服務(wù)端綁定成功吁朦!");
接收信息:
dispatch_queue_t queue = dispatch_queue_create("net.qigge.rec", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
while (1) {
int err;
struct sockaddr_storage addr;
socklen_t addrLen;
uint8_t buffer[65536];
ssize_t bytesRead;
addrLen = sizeof(addr);
bytesRead = recvfrom(_socketFileDescriptor, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &addrLen);
if (bytesRead < 0) {
err = errno;
} else if (bytesRead == 0) {
err = EPIPE;
} else {
NSData * dataObj;
NSData * addrObj;
err = 0;
dataObj = [NSData dataWithBytes:buffer length:(NSUInteger) bytesRead];
addrObj = [NSData dataWithBytes:&addr length:addrLen ];
}
}
});
服務(wù)端和客戶端都適用于發(fā)送UDP廣播和接收UDP廣播