免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3591 | 回复: 0
打印 上一主题 下一主题

[函数] UNIX网络编程(十七)-使用select 函数的TCP&UDP 回射服务器程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-03-15 21:23 |只看该作者 |倒序浏览
原文出处http://www.xinxi888.com/Library/www/UNIX/UNIX17.HTM
感谢原作者的贡献

使用select 函数的TCP&UDP 回射服务器程序是并发TCP回射服务器程序与迭代UDP回射

服务器程序使用select复用组合为TCP和UDP套接口的单个服务器程序.

    TCP并发服务器


  1. // TCP并发服务器
  2. int main(int argc, char **argv)
  3. { int listenfd, connfd;
  4. pid_t childpid;
  5. socklen_t clilen;
  6. struct sockaddr_in cliaddr, servaddr;
  7. void sig-chld(int);

  8. listenfd = Socket(AF_INET, SOCK_STREAM, 0);

  9. bzero(&servaddr, sizeof(servaddr));
  10. servaddr.sin_family = AF_INET;
  11. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  12. servaddr.sin_port = htons(SERV_PORT);

  13. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

  14. Listen(listenfd, LISTENQ);
  15. Signal(SIGCHLD, sig_chld); /* must call waitpid() */

  16. for ( ; ; ) {
  17. clilen = sizeof(cliaddr);
  18. if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
  19. if (errno == EINTR)
  20. continue; /* back to for() */
  21. else
  22. err_sys("accept error");
  23. }
  24. if ( (childpid = Fork()) == 0) { /* child process */
  25. Close(listenfd); /* close listening socket */
  26. str_echo(connfd); /* process the request */
  27. exit(0);
  28. }
  29. Close(connfd); /* parent closes connected socket */
  30. }
  31. }
复制代码


    用select函数的TCP&UDP回射服务器程序


  1. int main(int argc, char **argv)
  2. { int listenfd, connfd, udpfd, nready, maxfdp1;
  3. char mesg[MAXLINE]; pid_t childpid;
  4. fd_set rset;
  5. ssize_t n;
  6. socklen_t len;
  7. const int on = 1;
  8. struct sockaddr_in cliaddr, servaddr;
  9. void sig_chld(int);
  10. /*create listening TCP socket */
  11. listenfd = Socket(AF_INET, SOCK_STREAM, 0);
  12. bzero(&servaddr, sizeof(servaddr));
  13. servaddr.sin_family = AF_INET;
  14. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  15. servaddr.sin_port = htons(SERV_PORT);
  16. Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  17. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  18. Listen(listenfd, LISTENQ);
  19. /*create UDP socket */
  20. udpfd = Socket(AF_INET, SOCK_DGRAM, 0);
  21. bzero(&servaddr, sizeof(servaddr));
  22. servaddr.sin_family = AF_INET;
  23. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  24. servaddr.sin_port = htons(SERV_PORT);
  25. Bind(udpfd, (SA *) &servaddr, sizeof(servaddr));
  26. Signal(SIGCHLD, sig_chld); /* must call waitpid() */
  27. FD_ZERO(&rset);
  28. maxfdp1 = max(listenfd, udpfd) + 1
  29. for ( ; ; ) {
  30. FD_SET(listenfd, &rset);
  31. FD_SET(udpfd, &rset);
  32. if ( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
  33. if (errno == EINTR) continue; /* back to for() */
  34. else err_sys("select error");
  35. }
  36. if (FD_ISSET(listenfd, &rset)) {
  37. len = sizeof(cliaddr);
  38. connfd = Accept(listenfd, (SA *) &cliaddr, &len);
  39. if ( (childpid = Fork()) == 0) { /* child process */
  40. Close(listenfd); /* close listening socket */
  41. str_echo(connfd); /* process the request */
  42. exit(0);
  43. }
  44. Close(connfd); /* parent closes connected socket */
  45. }
  46. if (FD_ISSET(udpfd, &rset)) {
  47. len = sizeof(cliaddr);
  48. n = Recvfrom(udpfd, mesg, MAXLINE, 0, (SA *) &cliaddr, &len);
  49. Sendto(udpfd, mesg, n, 0, (SA *) &cliaddr, len);
  50. }
  51. }
  52. }

复制代码


    程序流程

定义变量

int listenfd : TCP监听套接口
int connfd: TCP已连接套接口,
int udpfd:UDP 套接口,
int nready:select函数中的准备好的描述字个数
int maxfdp1:select函数中的最大的描述字个数
char mesg[MAXLINE]:回射的字符串
pid_t childpid: TCP已连接套接口的进程编号
fd_set rset:select函数中的监听读描述字集
ssize_t n:回射的字符串的长度
socklen_t len:套接口地址长度
const int on = 1; 基本套接口选项SO_REUSEADDR的参数
SA cliaddr, servaddr :服务器客户套接口地址结构
void sig_chld(int);信号处理函数

创建TCP监听套接口

listenfd = Socket(AF_INET, SOCK_STREAM, 0); //建立TCP套接口描述字
bzero(&servaddr, sizeof(servaddr)); //地址结构清零
servaddr.sin_family = AF_INET; //IPv4协议
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //内核指定地址
servaddr.sin_port = htons(SERV_PORT); //总所诸知端口#9877
// 允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用作它们的本地端口的连接仍存在。
Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); //绑定本机地址和端口
Listen(listenfd, LISTENQ); //监听

创建UPD套接口

udpfd = Socket(AF_INET, SOCK_DGRAM, 0); //建立UDP套接口描述字
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(udpfd, (SA *) &servaddr, sizeof(servaddr)); //绑定本机地址和端口

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP