读书人

《Unix网络编程》:来射字符串的服务器

发布时间: 2012-11-20 09:55:44 作者: rapoo

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


运行示例(红色字体的为输入)
服务器端:
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



读书人网 >编程

热点推荐