logo资料库

Linux上实现基于Socket_的多进程实时通信.doc

第1页 / 共6页
第2页 / 共6页
第3页 / 共6页
第4页 / 共6页
第5页 / 共6页
第6页 / 共6页
资料共6页,全文预览结束
在 Linux 上实现基于 Socket 的多进程实时通信 本文提出一个基于 Socket 的多进程之间通信的实现方法。原理是建立一个进程专门用来做 为通信服务器(server)来中转各个进程之间的通信。它首先启 动一个用来监视连接要求的 listening Socket,并把它的描述(Descriptor)号加入到一个事先定义好的 fd_set 的集合中, 这个 fd_set 的集合用来存放 listening Socket 和后来生成的通信 Socket 的描述号。Server 运用 system call select 来实时检查是否有数据到达这个集合中的任何一个 socket,如果有数据到达 listening Socket,则这一定是客户端发起的连接请求,于是生成一个新的通信 Socket 与该客 户端连接,将生成的 Socket 描述号加入到 fd_set 的集合 中,将客户端的 ID 号和与之对应 的 Socket 的描述号记录在 ID 登记表中。如果有数据到达某个通信 Socket,则这一定是某个 客户端发起的通信请求, 读出数据并取出收信客户端 ID 号,在 ID 登记表中找到与之对应 的 Socket 描述号,将数据通过对应 Socket 传送到收信客户端。 其他各进程作为客户端(client)。客户端的动作是首先建立通信 Socket 连接服务器端,然后 通过通信 Socket 进行送信和收信。 首先给出 Server 端的程序,在这里假设有两个客户端要进行实时通信,ClientA 向 ClientB 发送字符 1,ClientB 向 ClientA 发送字符 2。 #include #include #include #include #include #include #include #include int main() { rcd ; backlog ; ci ; int struct sockaddr_un server_sockaddr ; int ushort int fd_set fd_set int new_cli_fd ; int maxfd; int struct sockaddr_un cli_sockaddr ; watch_fd_list[3] ; catch_fd_set ; watchset ; socklen ,server_len;
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]; 在上面的程序中,Server 生成 listening Socket(server_sockfd),初始化 Socket 监视集合 (watchset),并将 listening Socket 放入 Socket 监视集合中。 while (1){ char ch; int fd; int nread; catch_fd_set=watchset; rcd = select( maxfd+1, &catch_fd_set, NULL, NULL, (struct timeval *)0 ) ;
在上面的程序中,Server 运用系统调用函数 select 来实时检查是否有数据到达 Socket 监视 集合中的任何一个 socket。 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; } 在 上面的程序中,Server 运用系统调用函数 FD_ISSET 来检查是否有客户端的连接请求到 达 Listening Socket, 如果返回值大于 0,Server 生成一个新的通信 Socket (new_cli_fd) 与客户端连接。将新生成的通信 Socket 放入 Socket 监视集合中(FD_SET)。将客户端的 信息(ID 号和 Socket 描述号)保存在注册表 cli_info_t 中
for ( ci = 1; ci<=2 ; ci++ ) { int char char int dst_fd = -1 ; dst_module_id; src_module_id; 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 ) ; } } } 在上面的程序中,如果有数据到达某个通信 Socket,Server 则读出数据 并取出收信客户端 ID 号。在 ID 登记表中找到收信客户端对应的 Socket 描述号。并将数据通过对应 Socket 传 送到收信客户端 给出客户端 ClientA 的程序 ClientB 的程序只需将 char dst_module_id='B'; 改为 char dst_module_id='A'; char ch='1'; 改为 char char ch='2';既可。 #include
#include #include #include #include #include #include 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);
} 下面是样本程序的执行结果 [root@zhou test]# ./server & [3] 4301 [root@zhou test]# SERVER::Server is waitting on socket=3 ./clientA & ./clientB & [4] 4302 [5] 4303 ClientA::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 5 ClientB::succeed in connecting with server SERVER::char=1 to Client B on socket5 ClientB::char from Client A =1 SERVER::char=2 to Client A on socket4 ClientA::char from Client B =2
分享到:
收藏