可以使用recvmsg()来获取每个传入数据包的IP_TOS字段,或者只显示为特定套接字设置的IP_TOS值.如果没有,是否有人知道获得每个传入数据包的IP_TOS值的解决方案.我正在使用UDP应用程序,因此无法像TCP一样在应用程序层查看IP_TOS字段.谢谢.
struct msghdr msg; struct iovec iov[1]; memset(&msg,'\0',sizeof(msg)); msg.msg_iov = iov; msg.msg_iovlen = 1; iov[0].iov_base = (char *) &pkt; iov[0].iov_len = sizeof(pkt); struct cmsghdr cmsgcmsg[1]; msg.msg_control = cmsgcmsg; msg.msg_controllen = sizeof(struct cmsghdr); nRet = recvmsg(udpSocket,&msg,0); if (nRet > 0) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) { if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_TOS) && (cmsg->cmsg_len) ){ int tos = *(uint8_t *)CMSG_DATA(cmsg); int isecn = ((tos & INET_ECN_MASK) == INET_ECN_CE); printf("the tos = %i,is ecn = %d \n",tos,isecn); } }
解决方法
我终于设法解决了这个问题,并在这里添加了代码供其他人使用.我希望这对别人有帮助.这个是IP_TTL:
设置UDPSocket以接收IP_TTL值:
int ttl = 60; if(setsockopt(udpSocket,IPPROTO_IP,IP_RECVTTL,&ttl,sizeof(ttl))<0) { printf("cannot set recvttl\n"); } else { printf("socket set to recvttl\n"); }
并按以下方式从每个数据包中检索IP_TTL值(以下程序可以通过iov [0]检索数据消息,下面给出了代码片段):
struct msghdr msg; struct iovec iov[1]; memset(&msg,sizeof(msg)); msg.msg_iov = iov; msg.msg_iovlen = 1; iov[0].iov_base = (char *) &pkt; iov[0].iov_len = sizeof(pkt); int *ttlptr=NULL; int received_ttl = 0; int cmsg_size = sizeof(struct cmsghdr)+sizeof(received_ttl); // NOTE: Size of header + size of data char buf[CMSG_SPACE(sizeof(received_ttl))]; msg.msg_control = buf; // Assign buffer space for control header + header data/value msg.msg_controllen = sizeof(buf); //just initializing it nRet = recvmsg(udpSocket,0); if (nRet > 0) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) { if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_TTL) && (cmsg->cmsg_len) ){ ttlptr = (int *) CMSG_DATA(cmsg); received_ttl = *ttlptr; printf("received_ttl = %i and %d \n",ttlptr,received_ttl); break; } } }
可以通过以下方式发送和获取数据消息:
发件人方:
struct DATA_to_SEND pkt; struct msghdr msg; struct iovec iov[1]; memset(&msg,sizeof(msg)); msg.msg_iov = iov; msg.msg_iovlen = 1; iov[0].iov_base = (char *) &pkt; iov[0].iov_len = sizeof(pkt); nRet = sendmsg(udpSocket,0);
接收方(假设DATA_To_SEND有一个名为“seq”的参数):
struct DATA_to_SEND pkt; seqNum = ((struct DATA_to_SEND *) iov[0].iov_base)->seq;
以下是IP_TOS.
设置套接字以接收IP_TOS:
unsigned char set = 0x03; if(setsockopt(udpSocket,IP_RECVTOS,&set,sizeof(set))<0) { printf("cannot set recvtos\n"); } else { printf("socket set to recvtos\n");
并通过以下方式从每个数据包标头中检索IP_TOS值:
struct PC_Pkt pkt; int *ecnptr; unsigned char received_ecn; struct msghdr msg; struct iovec iov[1]; memset(&msg,sizeof(msg)); msg.msg_iov = iov; msg.msg_iovlen = 1; iov[0].iov_base = (char *) &pkt; iov[0].iov_len = sizeof(pkt); int cmsg_size = sizeof(struct cmsghdr)+sizeof(received_ecn); char buf[CMSG_SPACE(sizeof(received_ecn))]; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); nRet = recvmsg(udpSocket,0); if (nRet > 0) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) { if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_TOS) && (cmsg->cmsg_len) ){ ecnptr = (int *) CMSG_DATA(cmsg); received_ecn = *ecnptr; int isecn = ((received_ecn & INET_ECN_MASK) == INET_ECN_CE); printf("received_ecn = %i and %d,is ECN CE marked = %d \n",ecnptr,received_ecn,isecn); break; } } }