IP:TTL解释
虽然TTL从字面上翻译,是可以存活的时间,但实际上TTL是IP数据包在计算机网络中可以转发的最大跳数。TTL字段由IP数据包的发送者设置,在IP数据包从源到目的的整个转发路径上,每经过一个路由器,路由器都会修改这个TTL字段值,具体的做法是把该TTL的值减1,然后再将IP包转发出去。如果在IP包到达目的IP之前,TTL减少为0,路由器将会丢弃收到的TTL=0的IP包并向IP包的发送者发送 ICMP time exceeded消息。
TTL的主要作用是避免IP包在网络中的无限循环和收发,节省了网络资源,并能使IP包的发送者能收到告警消息。
TTL 是由发送主机设置的,以防止数据包不断在IP互联网络上永不终止地循环。转发IP数据包时,要求路由器至少将 TTL 减小 1。
GCDAsyncUdpSocket 组播 设置TTL
GCDAsyncUdpSocket 发送组播
socekt默认的ttl值为1
在GCDAsyncUdpSocket中没有设置默认ttl
所以在GCDAsyncUdpSocket中的ttl是1
设置ttl的方法为
选项IP_MULTICAST_TTL允许设置超时TTL,范围为0~255之间的任何值,例如:
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的话,就要设置GCDAsyncUdpSocket的TTL (默认TTL为1)
修改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;
}