GCDAsyncUdpSocket 设置TTL

xiaoxiao2021-02-28  112

IP:TTL解释

虽然TTL从字面上翻译,是可以存活的时间,但实际上TTLIP数据包在计算机网络中可以转发的最大跳数。TTL字段由IP数据包的发送者设置,在IP数据包从源到目的的整个转发路径上,每经过一个路由器,路由器都会修改这个TTL字段值,具体的做法是把该TTL的值减1,然后再将IP包转发出去。如果在IP包到达目的IP之前,TTL减少为0,路由器将会丢弃收到的TTL=0IP包并向IP包的发送者发送 ICMP time exceeded消息。

TTL的主要作用是避免IP包在网络中的无限循环和收发,节省了网络资源,并能使IP包的发送者能收到告警消息。

TTL 是由发送主机设置的,以防止数据包不断在IP互联网络上永不终止地循环。转发IP数据包时,要求路由器至少将 TTL 减小 1

GCDAsyncUdpSocket 组播 设置TTL

GCDAsyncUdpSocket 发送组播 

socekt默认的ttl值为1

GCDAsyncUdpSocket中没有设置默认ttl

所以在GCDAsyncUdpSocket中的ttl1

设置ttl的方法为

选项IP_MULTICAST_TTL允许设置超时TTL,范围为0255之间的任何值,例如: 

unsigned char ttl=255;

setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl));

本地回环

GCDAsyncUdpSocket 没有设置本地回环

默认是开启本地回环的,因此对于GCDAsyncUdpSocket默认是会收到本地回环信息的。

设置本地回环的方法为:

默认情况下,当本机发送组播数据到某个网络接口时,在IP层,数据会回送到本地的回环接口,选项IP_MULTICAST_LOOP用于控制数据是否回送到本地的回环接口。例如:

unsigned char loop;

setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));

getsockopt() 获取参数

 //组播224.0.0.2地址,如果地址大于224的话,就要设置GCDAsyncUdpSocketTTL (默认TTL1

修改GCDAsyncUdpSocket源代码:

- (BOOL)performMulticastRequest:(int)requestType forGroup:(NSString *)group onInterface:(NSString *)interface error:(NSError **)errPtr { __block BOOL result = NO; __block NSError *err = nil; dispatch_block_t block = ^{ @autoreleasepool { // Run through sanity checks if (![self preJoin:&err]) { return_from_block; } // Convert group to address NSData *groupAddr4 = nil; NSData *groupAddr6 = nil; [self convertNumericHost:group port:0 intoAddress4:&groupAddr4 address6:&groupAddr6]; if ((groupAddr4 == nil) && (groupAddr6 == nil)) { NSString *msg = @"Unknown group. Specify valid group IP address."; err = [self badParamError:msg]; return_from_block; } // Convert interface to address NSData *interfaceAddr4 = nil; NSData *interfaceAddr6 = nil; [self convertIntefaceDescription:interface port:0 intoAddress4:&interfaceAddr4 address6:&interfaceAddr6]; if ((interfaceAddr4 == nil) && (interfaceAddr6 == nil)) { NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address."; err = [self badParamError:msg]; return_from_block; } // Perform join if ((socket4FD != SOCKET_NULL) && groupAddr4 && interfaceAddr4) { const struct sockaddr_in *nativeGroup = (struct sockaddr_in *)[groupAddr4 bytes]; const struct sockaddr_in *nativeIface = (struct sockaddr_in *)[interfaceAddr4 bytes]; struct ip_mreq imreq; imreq.imr_multiaddr = nativeGroup->sin_addr; imreq.imr_interface = nativeIface->sin_addr; int status = setsockopt(socket4FD, IPPROTO_IP, requestType, (const void *)&imreq, sizeof(imreq)); // unsigned char ttl = 255; // status = setsockopt(socket4FD, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); //参数loop设置为0禁止回送,设置为1允许回送 //IP_MULTICAST_LOOP 禁止组播数据回送 unsigned char loop = 0; setsockopt(socket4FD, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); int ttlRead; socklen_t lenTTL=sizeof(int); if((getsockopt(socket4FD, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttlRead, &lenTTL)) == 0){ printf("udp TTl Value is : %d/n", ttlRead); } int loopRead; socklen_t len = sizeof(int); if((getsockopt(socket4FD, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopRead, &len)) == 0){ printf("udp loopRead Value is : %d/n", loopRead); } if (status != 0) { err = [self errnoErrorWithReason:@"Error in setsockopt() function"]; return_from_block; } // Using IPv4 only [self closeSocket6]; result = YES; }

转载请注明原文地址: https://www.6miu.com/read-72852.html

最新回复(0)