首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

《Unix网络编程》:来射字符串的服务器/客户端(TCP-epoll版)

2012-11-20 
《Unix网络编程》:回射字符串的服务器/客户端(TCP-epoll版)《Unix网络编程卷1:套接字联网API》这本书附带了许

《Unix网络编程》:回射字符串的服务器/客户端(TCP-epoll版)

    《Unix网络编程卷1:套接字联网API》这本书附带了许多短小精美的小程序,我在阅读此书的时候,将书上的代码按照自己的理解重写了一遍(大部分是抄书上的),加深一下自己的理解(纯看书太困了,呵呵)。此例子在Ubuntu10.04上测试通过。

 

    PS:程序里使用了包裹函数(首字母是大写的函数)和常量(所有字母都是大写的常量)的声明和定义在my_unp.h和my_unp.c中,地址:http://blog.csdn.net/aaa20090987/article/details/8096701

 

    程序简介:这一对例子演示了服务器和客户端使用select函数(模型)和TCP协议传输数据的基本原理和流程。当一个客户端连接上服务器时,服务器就修改fd_set集合与标志数组,来与客户端进行异步通信。

 

服务器端:

客户端:

[cpp] view plaincopyprint?
  1. #include "my_unp.h"  
  2.   
  3. void str_cli(FILE *fp, int sockfd)  
  4. {  
  5.     int maxfdp1;  
  6.     int stdineof;  
  7.     fd_set rset;  
  8.     char buf[MAXLINE];  
  9.     int n;  
  10.       
  11.     stdineof = 0;  
  12.     //清空rset集合中所有的元素  
  13.     FD_ZERO(&rset);  
  14.     while( 1 )  
  15.     {  
  16.         //在输入中没有遇见EOF时,把输入端的描述符fileno(fp)加入集合  
  17.         if( 0 == stdineof )  
  18.             FD_SET(fileno(fp), &rset);  
  19.         //把套接字的描述符加入集合  
  20.         FD_SET(sockfd, &rset);  
  21.   
  22.         //对最大描述符加1  
  23.         maxfdp1 = max(fileno(fp), sockfd+1);  
  24.   
  25.         //阻塞程序,等待某个事件的发生(见注解1)  
  26.         Select(maxfdp1, &rset, NULL, NULL, NULL);  
  27.   
  28.         //检查该套接字描述符是否在集合中  
  29.         if( FD_ISSET(sockfd, &rset) )  
  30.         {  
  31.             n = Read(sockfd, buf, MAXLINE);  
  32.             //当在套接字上读到EOF时,  
  33.             //若输入端中已经读到EOF,那么客户端就正常退出了  
  34.             //否则,就是服务器中断了服务  
  35.             if( n == 0 )  
  36.             {  
  37.                 if( 1 == stdineof )  
  38.                     return;  
  39.                 else  
  40.                     error_quit("str_cli: server terminated prematurely");  
  41.             }  
  42.             Write(fileno(stdout), buf, n);  
  43.         }  
  44.   
  45.         if( FD_ISSET(fileno(fp), &rset) )  
  46.         {  
  47.             n = Read(fileno(fp), buf, MAXLINE);  
  48.             //当在输入中遇见EOF时,先将设置标志位,然后调用shutdown来发送FIN  
  49.             if( 0 == n )  
  50.             {  
  51.                 stdineof = 1;  
  52.                 Shutdown(sockfd, SHUT_WR);  
  53.                 FD_CLR(fileno(fp), &rset);  
  54.                 continue;  
  55.             }  
  56.             Writen(sockfd, buf, n);  
  57.         }  
  58.     }  
  59. }  
  60.   
  61. int main(int argc, char **argv)  
  62. {  
  63.     int sockfd;  
  64.     struct sockaddr_in servaddr;  
  65.     if( argc != 2 )  
  66.         error_quit("usage: client <IPAddress>");  
  67.   
  68.     //创建用于TCP协议的套接字   
  69.     sockfd = Socket(AF_INET, SOCK_STREAM, 0);  
  70.     memset(&servaddr, 0, sizeof(servaddr));  
  71.     servaddr.sin_family = AF_INET;  
  72.     servaddr.sin_port = htons(SERV_PORT);  
  73.   
  74.     //将程序的参数1(argv[1])转换成套接字地址结构  
  75.     Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);  
  76.     ////向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接   
  77.     Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));  
  78.   
  79.     str_cli(stdin, sockfd);  
  80.     return 0;  
  81. }  


运行示例(红色字体的为输入)
服务器端:
qch@ubuntu:~/code$ gcc my_unp.c server.c -o server
qch@ubuntu:~/code$./server
connection from 127.0.0.1, port 47595
Ctrl+D
客户端:
qch@ubuntu:~/code$gcc my_unp.c client.c -o client
qch@ubuntu:~/code$./client 127.0.0.1
hello, world
hello, world
#此时关闭服务器
str_cli:server terminated prematurely



热点排行