![]() ![]() |
|
TCP/IP网络重复型服务器通信软件的设计(二) | |
作者:佚名 文章来源:不详 点击数 更新时间:2008/4/18 13:58:31 文章录入:杜斌 责任编辑:杜斌 | |
|
|
listen(s_c1,5); s_w=accept(s_c1,&peeraddr_in,&addrlen); close(s_c1); /*只允许接收一次连接请求*/ linger.l_onoff=1;linger.l_linger=0; setsockopt(s_w,SOL_SOCKET,SO_LINGER,&linger,sizeof(struct linger)); listen(s_c2,5); s_r=accept(s_c2,&peeraddr_in,&addrlen); close(s_c2); setsockopt(s_r,SOL_SOCKET,SO_LINGER,&linger,sizeof(struct linger)); 来源:www.examda.com ⑸ 进程tcp_s1调用函数Server_Receive在一个循环中不断查询是否又有新的客户机登记在共享内存中,方法是判断共享内存中最后一条记录的linkf1标志是否为0,如果为0就调函数connect_to_client与客户机建立第一个连接,然后轮询所有的读套接字,有数据则读,没有数据则读下一个读套接字。 Server_Receive(){ int s1,len,i,linkn,linkf1,n; struct msg_buf *buf,mbuf; buf=&mbuf; for(;;){ linkn=shm_info(0,GETLINKN); linkf1=shm_info(linkn,GETLINKF1); if(linkf1==0){ if((i=connect_to_client(linkn,1))<0){ shm_logout(linkn);continue; } } for(n=1;n<=linkn;n++){ s1=shm_info(n,GETS1); i=read(s1,buf,MSGSIZE); if(i==0){ fprintf(stderr,"A client exit!\n"); shutdown(s1,1);close(s1); shm_logout(n); linkn--;continue; } if(i==-1) continue; buf->mtype=MSGTYPE;buf->sid=n; len=strlen(buf->mdata); fprintf(stderr,"mdata=%s\n",buf->mdata); i=msgsnd(qid3,buf,len+BUFCTLSIZE+1,0); } } }
由于已将读套接字的读取标志设为O_NDELAY,所以没有数据可读时read函数就返回-1不会堵塞住。这样我们才能接收到客户机随机的数据发送同时也才能及时响应新的客户机的连接请求,这是重复服务器得以实现的关键所在。如果read函数返回0则表示客户机通信程序已退出或者别的原因,比如客户机关机或网络通信故障等,此时就要从共享内存中清除相应客户机的记录。在建立连接时如果出现上述故障也要从共享内存中清除相应客户机的记录。在有数据可读时就将sid标志设置为n,表示数据是从第n台客户机读取的,这样子进程tcp_s2才可根据消息的sid标志往第n台客户机写数据。 ⑹ 进程tcp_s2调用函数Server_Send,在一个循环中不断查询是否又有新的客户机连接登记在共享内存中,方法是判断共享内存中最后一条记录的linkf2标志是否为0,如果为0就调用函数connect_to_client与客户机建立第二个连接,然后再从消息队列中读数据。因为只有一个tcp_s2进程在读消息队列,所以就不必对消息进行区别,有数据则读。再按照消息的sid标志从共享内存中查出写套接字,然后将数据往该套接字写。由于该写套接字是在进程tcp_s2内创建的,所以只要简单地使用套接字的句柄即可访问该套接字。函数msgrcv要设置IPC_NOWAIT标志以免在没有数据时堵塞住,这样才能继续执行下面的程序以便及时地与下一台客户机建立连接,这也是一个关键的地方。tcp_s2调用函数Server_Send用于数据发送,tcp_s1则调用函数Server_Recvice用于数据接收。 Server_Send(){ int s2,linkn,linkf2,i; struct msg_buf *buf,mbuf; buf=&mbuf; for(;;){ linkn=shm_info(0,GETLINKN); linkf2=shm_info(linkn,GETLINKF2); if(linkf2==0){ if((i=connect_to_client(linkn,2))<0){ shm_logout(linkn);continue; } } i=msgrcv(qid4,buf,MSGSIZE,MSGTYPE,0x1ff|IPC_NOWAIT); if(i==-1) continue; s2=shm_info(buf->sid,GETS2); if(write(s2,buf,i+1)!=i+1){ perror("write");close(s2); } } } |
|
![]() ![]() |