The sendmsg and recvmsg functions are a pair of lower-layer socket sending and receiving functions. Through this function, we can set or obtain some additional control information of the data packet, which is commonly used in the sending and receiving interface information described in this article. Through this function, we can specify the interface (NIC) used when a data packet is sent or obtain a source interface that receives the data packet. The most important thing in the sendmsg (FD, & mhdr, 0) function is the msghdr struct. It is defined as follows:
Struct msghdr {void * msg_name; # Sending address socklen_t msg_namelen; # The former length struct iovec * msg_iov; # The sending data buffer pointer size_t msg_iovlen; # The sending data length void * msg_control; # Control Data Pointer size_t msg_controllen; # Control Data Length int msg_flags ;};
Before sending a data packet, you must first enter the data to be sent and related control information in this struct.
This struct contains pointers to data and control information. Therefore, before sending data, we need to allocate space for data and control information.
Needless to say, the data can be directly char Buf [max_msg_size. The difficulty lies in the control information.
First, define an msghdr struct to store all control information and sent data packets:
Struct msghdr mhdr;
Then define the control information structure cmsghdr:
Struct cmsghdr * cmsg;
First, we need to use the cmsg_space macro to calculate the size of the space required to control the cmsghdr struct, and then allocate memory for the control struct pointer. The size of cmsghdr depends on the control message to be filled in. Here we need to fill in the sending interface control information. This control information also needs to be carried by the struct in6_pktinfo structure, so the size of cmsghdr is related to the size of in6_pktinfo:
Struct in6_pktinfo PK; // defines the interface to control the data structure PK. ini_index = 1; // specify the interface (here 1 is the interface index number) cmsglen = cmsg_space (sizeof (PK); // calculate the size required by the cmsghdr structure in mhdr. msg_control = (void *) malloc (cmsglen); // allocate memory for cmsghdr and fill in the control information pointer mhdr in mhdr. msg_controllen = cmsglen; cmsg = cmsg_firsthdr (& mhdr ); // We use cmsg_firsthdr to find the real address of the control information in the mhdr struct. // use cmsg_len to calculate the actual length of the control data in the cmsghdr structure. cmsg_len = cmsg_len (sizeof (* PK )); cmsg-> cmsg_level = ipproto_ipv6; // enter the cmsghdr control information structure cmsg-> cmsg_type = rj6_pktinfo; // cmsg_data (cmsg) to find the position of the control information in the cmsghdr structure, then we can use memcpy to copy the data of the control struct to cmsg: memcpy (cmsg_data (cmsg), PK, sizeof (* PK ));
The above is the sending process, and the receiving process is similar to the sending process. It is best to note that to send and receive such control information, we must set socket options:
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;