Implement socket-based multi-process real-time communication in Linux
Zhou Xin (jones_zhou@yahoo.com.cn ),
Software Engineer
Introduction:Socket is the most widely used inter-process communication mechanism in Linux. However, it cannot be directly used for real-time communication between multiple processes. This paper proposes a socket-based multi-process communication implementation method, and provides the implementation and description of the sample program.
Label of this article:Linux and socket are implemented based on,
Multi-process real-time communication
Mark this article!
Release date:March 01, 2005
Level:Elementary
Access:8722 views
Comment:1 (View | Add comment-Log On)
Average score (21 scores)
Score for this article
Socket is the most widely used inter-process communication mechanism in Linux, different from other Linux communication mechanisms, it can be used for communication between processes in a single machine, but also between processes between different machines. However, because the socket itself does not support concurrent waiting and timeout processing, it cannot directly use multi-process mutual real-time communication.
This article proposes a socket-based multi-process communication implementation method. The principle is to establish a process dedicated to serve as a communication server to transit communication between processes. It first starts a listening socket to monitor connection requirements, and adds its description (descriptor) number to a previously defined fd_set collection, the fd_set set is used to store the description numbers of the listening socket and the communication socket generated later. Server uses System Call select to check whether any data arrives at any socket in the Set in real time. If any data arrives at listening
Socket, this must be a connection request initiated by the client. Therefore, a new communication socket is generated to connect to the client, and the generated socket description is added to the fd_set collection, record the Client ID and the corresponding socket description in the ID registration form. If data arrives at a communication socket, it must be a Communication Request initiated by a client. Read the data and retrieve the ID of the receiver client. In the ID registration form, find the corresponding socket description number, transmit data to the receiving client through the corresponding socket.
Other processes act as clients ). The client first establishes a communication socket to connect to the server, and then sends and receives messages through the communication socket.
The following describes the specific program implementation and description,
First, the server program is provided. Here we assume there are two clients for real-time communication. clienta sends 1 character to clientb and 2 character to clienta.
#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <sys/un.h>#include <sys/time.h>#include <sys/ioctl.h>#include <unistd.h>#include <netinet/in.h>int main(){ int rcd ; struct sockaddr_un server_sockaddr ; int backlog ; ushort ci ; int watch_fd_list[3] ; fd_set catch_fd_set ; fd_set watchset ; int new_cli_fd ; int maxfd; int socklen ,server_len; struct sockaddr_un cli_sockaddr ; struct { char module_id ; /* Module ID */ int cli_sock_fd ; /* Socket ID */ } cli_info_t[2] ; for (ci=0; ci<=1; ci++) cli_info_t[ci].cli_sock_fd=-1; for (ci=0; ci<=2; ci++) watch_fd_list[ci]=-1; int server_sockfd,client_sockfd; server_sockfd = socket( AF_UNIX, SOCK_STREAM, 0 ) ; server_sockaddr.sun_family = AF_UNIX ; strcpy( server_sockaddr.sun_path, "server_socket" ) ; server_len=sizeof(server_sockaddr); rcd = bind( server_sockfd, ( struct sockaddr * )&server_sockaddr, server_len ) ; backlog = 5 ; rcd = listen( server_sockfd, backlog ) ; printf("SERVER::Server is waitting on socket=%d \n",server_sockfd); watch_fd_list[0]=server_sockfd; FD_ZERO( &watchset ) ; FD_SET( server_sockfd, &watchset ) ; maxfd=watch_fd_list[0];
In the above program, the server generates the listening socket (server_sockfd), initializes the socket monitoring set (watchset), and puts the listening socket into the socket monitoring set.
while (1) { char ch; int fd; int nread; catch_fd_set=watchset; rcd = select( maxfd+1, &catch_fd_set, NULL, NULL, (struct timeval *)0 ) ;
In the above program, the server uses the system call function select to check whether data has arrived in any socket in the socket monitoring set in real time.
if ( rcd < 0 ) { printf("SERVER::Server 5 \n"); exit(1); } if ( FD_ISSET( server_sockfd, &catch_fd_set ) ) { socklen = sizeof( cli_sockaddr ) ; new_cli_fd = accept( server_sockfd, ( struct sockaddr * ) &( cli_sockaddr ), &socklen ) ; printf(" SERVER::open communication with Client %s on socket %d\n", cli_sockaddr.sun_path,new_cli_fd); for (ci=1; ci<=2; ci++) { if(watch_fd_list[ci] != -1) continue; else { watch_fd_list[ci] = new_cli_fd; break; } } FD_SET(new_cli_fd , &watchset ) ; if ( maxfd < new_cli_fd ) { maxfd = new_cli_fd ; } for ( ci=0; ci<=1; ci++) { if(cli_info_t[ci].cli_sock_fd == -1) { cli_info_t[ci].module_id=cli_sockaddr.sun_path[0]; cli_info_t[ci].cli_sock_fd=new_cli_fd; break; } } continue; }
In the preceding program, the server uses the system call function fd_isset to check whether a client connection request has arrived at the listening socket. If the returned value is greater than 0, the server generates a new communication socket (new_cli_fd) connect to the client. Place the new communication socket into the socket monitoring set (fd_set ). Save the client information (ID and socket description) in the Registry cli_info_t.
for ( ci = 1; ci<=2 ; ci++ ) { int dst_fd = -1 ; char dst_module_id; char src_module_id; int i; if (watch_fd_list[ ci ]==-1) continue; if ( !FD_ISSET( watch_fd_list[ ci ], &catch_fd_set ) ) { continue ; } ioctl(watch_fd_list[ ci ],FIONREAD,&nread); if (nread==0) { continue; } read( watch_fd_list[ ci ], &dst_module_id, 1 ) ; for (i=0; i<=1; i++) { if(cli_info_t[i].module_id == dst_module_id) dst_fd= cli_info_t[i].cli_sock_fd; if(cli_info_t[i].cli_sock_fd==watch_fd_list[ ci ]) src_module_id= cli_info_t[i].module_id; } read( watch_fd_list[ ci ], &ch, 1 ) ; printf("SERVER::char=%c to Client %c on socket%d\n",ch, dst_module_id,dst_fd); write(dst_fd,&src_module_id, 1 ) ; write(dst_fd,&ch, 1 ) ; } }}
In the preceding program, if data reaches a communication socket, the server reads the data and obtains the ID of the receiver client. In the ID registration form, find the socket description number corresponding to the email receiving client. And transmit the data to the receiving client through the corresponding socket
Client client program
The clientb program only needs to change char dst_module_id = 'B'; To char dst_module_id = 'a'; char CH = '1'; To char CH = '2.
#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <sys/un.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>int main(){ int client_sockfd; int len; struct sockaddr_un server_sockaddr,cli_sockaddr; int result; char dst_module_id='B'; char ch='1'; char src_module_id; client_sockfd= socket(AF_UNIX,SOCK_STREAM,0); cli_sockaddr.sun_family = AF_UNIX ; strcpy( cli_sockaddr.sun_path, "A" ) ; bind(client_sockfd,(struct sockaddr * )&cli_sockaddr, sizeof( cli_sockaddr ) ) ; server_sockaddr.sun_family=AF_UNIX; strcpy( server_sockaddr.sun_path, "server_socket" ) ; len=sizeof(server_sockaddr); result = connect(client_sockfd,( struct sockaddr * )&server_sockaddr,len); if (result <0) { printf("ClientA::error on connecting \n"); exit(1); } printf("ClientA::succeed in connecting with server\n"); sleep(10); write(client_sockfd,&dst_module_id,1); write(client_sockfd,&ch,1); read (client_sockfd,&src_module_id,1); read (client_sockfd,&ch,1); printf("ClientA::char from Client %c =%c\n", src_module_id,ch); close (client_sockfd);}
The following is the execution result of the sample program.
[root@zhou test]# ./server &[3] 4301[root@zhou test]# SERVER::Server is waitting on socket=3./clientA & ./clientB &[4] 4302[5] 4303ClientA::succeed in connecting with server SERVER::open communication with Client A on socket 4[root@zhou test]# SERVER::open communication with Client B on socket 5ClientB::succeed in connecting with serverSERVER::char=1 to Client B on socket5ClientB::char from Client A =1SERVER::char=2 to Client A on socket4ClientA::char from Client B =2
Download the program list: Server. C, clienta. c
About the author
Zhou Xin graduated from the computer department of Beijing University of Posts and Telecommunications and is now engaged in software development in Japan.
Jones_zhou@yahoo.com.cn can contact him.
Reprinted from http://www.ibm.com/developerworks/cn/linux/l-socket-ipc/index.html