struct msghdr { void *msg_name; #发送地址 socklen_t msg_namelen; #前者长度 struct iovec *msg_iov;#发送数据缓冲区的指针 size_t msg_iovlen;#发送数据长度 void *msg_control; #控制数据指针 size_t msg_controllen;#控制数据长度 int msg_flags; };
在我们发送一个数据包之前,要首先把要发送的数据以及相关控制信息填写到这个结构体中。
这个结构体中包含的是数据以及控制信息的指针,因此在发送之前我们还需要另外为数据和控制信息分配空间。
数据就不用说了,直接char buf[MAX_MSG_SIZE]即可。难点在于控制信息。
首先要定义一个msghdr 结构体,这个结构体用来存储所有的控制信息和发送的数据包:
struct msghdr mhdr;
接着定义控制信息结构体cmsghdr :
struct cmsghdr *cmsg;
我们要首先通过CMSG_SPACE 宏计算出控制信息cmsghdr结构体所需的空间大小,接着为控制信息结构体指针分配内存。cmsghdr的大小跟你要填写的控制消息有关。我们这里要填写的是发送接口控制信息,这个控制信息还需要一个结构体struct
in6_pktinfo结构体来承载,所以这里cmsghdr的大小则跟in6_pktinfo的大小有关:
struct in6_pktinfo pk;//定义接口控制数据结构 pk.ini_index=1;//指定接口(这里的1是接口索引号) cmsglen = CMSG_SPACE (sizeof(pk));//计算cmsghdr结构在mhdr中所需的大小 mhdr.msg_control=(void *)malloc(cmsglen);//为cmsghdr分配内存,并在mhdr中填写控制信息的指针 mhdr.msg_controllen=cmsglen; cmsg = CMSG_FIRSTHDR (&mhdr);//我们利用CMSG_FIRSTHDR找到控制信息在mhdr结构体中的真正地址 //利用CMSG_LEN算出控制信息cmsghdr结构中真正的控制数据的长度 cmsg->cmsg_len = CMSG_LEN(sizeof(*pk)); cmsg->cmsg_level = IPPROTO_IPV6;//填写cmsghdr控制信息结构体 cmsg->cmsg_type = IPV6_PKTINFO; //CMSG_DATA(cmsg) 可以找到真正的控制信息在cmsghdr结构体中的位置,之后我们就可以利用memcpy把控制结构体的数据拷贝到cmsg中: memcpy(CMSG_DATA(cmsg), pk, sizeof(*pk));
int val = 1; if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)) < 0) return -1; if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &val, sizeof(val)) < 0) return -1; if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR, &val, sizeof(val)) < 0) return -1;
利用sendmsg和recvmsg来指定发送接口或者获取接收数据接口,布布扣,bubuko.com
利用sendmsg和recvmsg来指定发送接口或者获取接收数据接口
原文地址:http://blog.csdn.net/l1902090/article/details/37742297