Recently in the study of "Linux High Performance Server Programming" This book, the book Fragmented some knowledge of TCP out-of-band data, here to summarize the following, convenient for themselves, but also convenient for others.
This paper is divided into the following four aspects summarized, respectively, the concept of TCP out-of-band data, how to send and receive out-of-band data, how to detect the arrival of out-of-band data, and finally introduce related functions and code implementation.
The first part: The concept of TCP out-of-band data
有很多传输层此协议都具有带外数据(OUT Of Band) 的概念,其作用是迅速通告通信的另一方本段发生的重要事件。带外数据具有比普通数据更高的优先级,理论上应该被立即发送和立即接收。带外数据可以使用一条独立的传输层连接,也可以映射到传输普通数据的连接中。 UDP并没有实现带外数据,TCP也没有真正的带外数据。 TCP利用其头部中的紧急指针标志以及紧急指针字段,给应用程序提供里一种紧急方式。所以TCP是利用传输普通数据的连接来传输带外数据。
Part II: Sending and receiving TCP out-of-band data
1. TCP out-of-band data sending process:
Suppose a process has written to a TCP connection's send buffer to write n bytes of normal data and waits for it to be sent. Before the data is sent, the process writes to the connection 3 bytes of out-of-band data "ABC". At this point, the head of the TCP segment to be sent is flagged by the snake Urg, and the emergency pointer points to the next byte of the out-of-band data .
the multi-byte out-of-band data sent by the sending side only the last byte is treated as out -of-band data, and the other data is treated as normal data.
2. TCP out-of-band data reception process
The TCP receiver checks the emergency pointer only when it receives a TCP datagram relaying with an emergency flag, and then determines the location of the out-of-band data based on the location pointed to by the emergency pointer and reads it into a special cache . This cache has only one byte, called an out -of-band cache.
Part III: How the kernel notifies the application of out-of-band data arrival
There are two main ways of doing this:
1. The call of the IO multiplexing (select mode multiplexing) system reports an exception event;
The purpose of the select system call is to listen for readable, writable, and unusual events on the file descriptors that are of interest to the user for a specified period of time. Similarly, select system calls can listen for readable, writable, and anomalous times on the socket. in a network program, there is only one exception that can be handled by select: Out-of-band data is received on the socket .
The specific steps are: First set the Select listener we care about the socket descriptor, when an event occurs, determine the time type, if the time type is the socket exception time, it indicates that there is emergency data, can read the emergency data.
2. Sigurg Signal
It is implemented by registering the Sigurg signal and its signal processing function in the process, and receiving the emergency data within the Sigurg signal processing function when the process receives the Sigurg signal. at this point the mode of the signal is Sa_restart, indicating that the system call interrupted by the signal continues on when the signal is returned.
Part IV: Correlation function and code implementation
1. Related functions
(1) Send receive out-of-band data and send to receive normal data, you can use the Send () and recv () function. The difference is that the last parameter of the function int flags is different.
#include <sys/types.h>#include <sys/socket.h>ssize_t recv(int sockfd,void* buf,size_t len,int flags);ssize_t send(int sockfd,constvoid* buf,size_t len,int flags);//将fags 设置为 MSG_OOB 表示结束和发送带外数据。
(2) Select system Call correlation function
#include <sys/select.h>int Select(intNfds, fd_set* Readfds, fd_set* Writefds, fd_set* Exceptfds,structtimeval* timeout);The //nfds parameter represents the total number of file descriptors that are listening, typically the maximum file descriptor for the Listener + 1. The//readfds points to a set of descriptors that need to listen for a readable event, Writefds points to a descriptor collection that needs to listen for writable events, and Exceptfds points to a descriptor collection that needs to listen for exceptions////Fd_zero (fd_set* fdset);//Clears all descriptors in the description descriptor FdsetFd_set (intfd,fd_set* fdset);//To Description descriptor Fdset Add descriptor FDFD_CLR (intfd,fd_set* fdset);//Clear Descriptor in Description descriptor Fdset FDintFd_isset (intfd,fd_set* fdset);//Test Description Descriptor Fdset Whether descriptor FD is set
(3) SIGUSR signal processing correlation function
#include <signal.h>#include <fcntl.h>int sigaction (intconststructstruct sigaction* oact);//sig参数指定要绑定的信号,在这里就是SIGUSR//act 参数绑定了信号处理函数指针,指定里信号的处理方式以及设置里信号掩码//其中act.sa_handler 赋值为信号处理函数的指针//使用SIGUSR之前 ,必须设置socket的宿主进程或者进程组,使用下面的函数fcntl(sockfd,F_SETOWN,getpid());
2. Code implementation
The code implements a client and a server side, the client sends both the out-of-band data and the normal data, the server side in two ways to receive both the out-of-band data and receive ordinary data and display, can be set by different parameters at startup to receive in different ways.
The client sends normal data 123, out-of-band data abc, normal data 123, client input two parameters, parameter 1 server address, parameter 2 server listening port. Server-side receive data, server program has three input parameters, parameter 1 server's binding address, Parameter 2 server's binding port, Parameter 3 is 1 with select multiplexing Receive, Parameter 3 is 2 with sigusr signal method.
Client code:
#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <assert.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>intMain (intargcChar* argv[])//Parameter 1 is the server IP address, parameter 2 is the server's listening port{if(argc<=2) {printf("Usage:%s ip_address port_number\n", BaseName (argv[0]));return 1; }Const Char* IP = argv[1];//Get IP parameters intPort = atoi (argv[2]);//Get port parameters structSockaddr_in server_address;memset(&server_address,0,sizeof(server_address)); server_address.sin_family = af_inet; Inet_pton (AF_INET,IP,&SERVER_ADDRESS.SIN_ADDR);//Set the address structure body IPServer_address.sin_port = htons (port);//Set the address structure body Port intSOCKFD = socket (Pf_inet,sock_stream,0);//Birth Complete socketASSERT (sockfd>=0);if(Connect (SOCKFD,structsockaddr*) &server_address,sizeof(server_address)) <0) {printf("Connection failed!\n"); }Else{Const Char* Oob_data ="ABC";Const Char* Normal_data ="123"; Send (Sockfd,normal_data,strlen(Normal_data),0);//Send normal dataSend (Sockfd,oob_data,strlen(Oob_data), Msg_oob);//Send out -of-band dataSend (Sockfd,normal_data,strlen(Normal_data),0);//Send normal data} close (SOCKFD);//Close socket return 0;}
Server-side code
#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <assert.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <stdlib.h>#include <signal.h>Static intCONNFD;voidSig_urg (intSig//Signal processing function to receive out-of-band data in the signal processing function{intSave_errno = errno;Charbuffer[1024x768];memset(Buffer,0,1024x768);intret = recv (Connfd,buffer,1023, Msg_oob);//Receive out -of-band data printf("got%d bytes of OOB data '%s ' \ n", Ret,buffer); errno = Save_errno;}voidAddsig (intSigvoid(*sig_handler) (int))//Register signal processing function, set signal processing mode and mask{structSigaction sa;memset(&sa,0,sizeof(SA)); Sa.sa_handler = Sig_handler; Sa.sa_flags |= Sa_restart; Sigfillset (&sa.sa_mask); ASSERT (Sigaction (sig,&sa,null)!=-1);}intMainintargcChar* argv[]) {if(ARGC <=3) {printf("Usage:%s ip_address port_number method\n", BaseName (argv[0]));return 1; }Const Char* IP = argv[1];intPort = atoi (argv[2]);intmethod = Atoi (argv[3]);intRET =0;structSockaddr_in address;memset(&address,0,sizeof(address)); address.sin_family = af_inet; Inet_pton (Af_inet, IP, &address.sin_addr); Address.sin_port = htons (port);intLISTENFD = socket (Pf_inet,sock_stream,0);//Birth Complete socketASSERT (listenfd>=0); ret = bind (LISTENFD, (structsockaddr*) &address,sizeof(address));//Bound socketsASSERT (ret!=-1); RET = Listen (LISTENFD,5);//Set monitoringASSERT (ret!=-1);structSockaddr_in client_address;//Client addresssocklen_t client_addrlength =sizeof(client_address); CONNFD = Accept (LISTENFD, (structsockaddr*) &client_address,&client_addrlength);//Receive client connections if(connfd<0) {printf("errno is:%d\n", errno); Close (LISTENFD); }if(Method = =1)//select multiplexing mode receives out -of-band data{Charbuf[1024x768]; Fd_set Read_fds;//need to listen for a description of readable information descriptorFd_set Exception_fds;//Description of the need to listen for exception information descriptorFd_zero (&read_fds);//Clear Description DescriptorFd_zero (&exception_fds);//Emptying Exception Description descriptor while(1) {memset(BUF,' + ',sizeof(BUF)); Fd_set (Connfd,&read_fds);//Add socket to listen-readable description descriptorFd_set (Connfd,&exception_fds);//Add socket to Listener Exception description descriptorret = SELECT (connfd+1, &read_fds,null,&exception_fds,null);//Start multiplexing monitoring if(Ret <0) {printf("Selection failure\n"); Break; }if(Fd_isset (Connfd,&read_fds))//have normal data to come readable{memset(BUF,' + ',sizeof(BUF)); ret = recv (Connfd,buf,sizeof(BUF)-1,0);if(Ret <=0) { Break; }printf("Get%d bytes of normal data:%s\n", RET,BUF); }if(Fd_isset (Connfd,&exception_fds))//There is an abnormal occurrence, that is, out of band data arrival{FD_CLR (CONNFD,&EXCEPTION_FDS);//clear the corresponding bit in the descriptor set, otherwise the program is not working properly memset(BUF,' + ',sizeof(BUF)); ret = recv (Connfd,buf,sizeof(BUF)-1, Msg_oob);if(Ret <=0) { Break; }printf("Get%d bytes of OOB data:%s\n", RET,BUF); Fd_set (Connfd,&exception_fds);//re-join Description descriptor}} close (CONNFD);//Shut-off socketClose (LISTENFD);//Turn off the listener socket return 0; }Else if(Method = =2)//Use Sigurg to detect if out-of-band data arrives{Addsig (Sigurg,sig_urg);//Register signal set signal processing functionFcntl (Connfd,f_setown,getpid ());//Set the main process for sockets Charbuffer[1024x768]; while(1) {memset(Buffer,0,1024x768); ret = recv (Connfd,buffer,1023,0);if(Ret <=0) { Break; }printf("got%d bytes of normal data '%s ' \ n", Ret,buffer); } close (CONNFD); Close (LISTENFD);return 0; }}
The above is my summary of the TCP out-of-band data-related knowledge, because I am a student, no practical experience, paper on the end of the shallow, so take a summary write to deepen the impression. Welcome to criticize and correct!
TCP out-of-band Data Learning summary (concept, send receive process, data arrival detection, code implementation)