并发UDP服务器

前端之家收集整理的这篇文章主要介绍了并发UDP服务器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

服务器端代码如果采用fork写时复制(Copy on Write)技术,代码还可以更简洁一点

服务端代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <netdb.h>
  8. #include <arpa/inet.h>
  9. #define BUFSIZE 4096
  10. #define CHILD_PORT_START 16500
  11.  
  12. const char* Inet_ntop(void* ptr) {
  13. static char str[INET_ADDRSTRLEN];
  14. return inet_ntop(AF_INET,ptr,str,INET_ADDRSTRLEN);
  15. }
  16.  
  17. void server_echo(int sockfd) {
  18. int fullfd[2];
  19. if (socketpair(AF_UNIX,SOCK_DGRAM,0,fullfd) < 0) {
  20. printf("sockpair error: %s\n",strerror(errno));
  21. exit(1);
  22. }
  23. char recv[BUFSIZE];
  24. struct sockaddr_in clientaddr;
  25. socklen_t len = sizeof(struct sockaddr_in);
  26. ssize_t n;
  27. struct iovec iov[2];
  28. int pid;
  29. for (; ;) {
  30. if ((n = recvfrom(sockfd,recv,BUFSIZE,(struct sockaddr*)&clientaddr,&len)) < 0) {
  31. printf("receive from client error: %s\n",strerror(errno));
  32. break;
  33. }
  34. iov[0].iov_base = &clientaddr;
  35. iov[0].iov_len = len;
  36. iov[1].iov_base = recv;
  37. iov[1].iov_len = n;
  38. if (writev(fullfd[0],iov,2) != n + len) {
  39. printf("writev to child error: %s\n",strerror(errno));
  40. exit(1);
  41. }
  42. if ((pid = fork()) < 0) {
  43. printf("fork error: %s\n",strerror(errno));
  44. break;
  45. }else if (pid == 0) {
  46. struct sockaddr_in to;
  47. socklen_t tolen = sizeof(struct sockaddr_in);
  48. int childfd;
  49. struct sockaddr_in server;
  50. server.sin_family = AF_INET;
  51. server.sin_port = getpid() - getppid() + CHILD_PORT_START;
  52. server.sin_addr.s_addr = htonl(INADDR_ANY);
  53. struct iovec get[2];
  54. char send[BUFSIZE];
  55. ssize_t count = n;
  56. get[0].iov_base = &to;
  57. get[0].iov_len = sizeof(struct sockaddr_in);
  58. get[1].iov_base = send;
  59. get[1].iov_len = BUFSIZE;
  60. if (readv(fullfd[1],get,2) != count + tolen) {
  61. printf("readv error: %s\n",strerror(errno));
  62. exit(1);
  63. }
  64. printf("child process pid = %d handle from IP: %s client\n",getpid(),Inet_ntop(&to.sin_addr));
  65. if ((childfd = socket(AF_INET,IPPROTO_UDP)) < 0) {
  66. printf("child socket error: %s\n",strerror(errno));
  67. }
  68. if (bind(childfd,(struct sockaddr*)&server,sizeof(struct sockaddr_in)) < 0) {
  69. printf("child bind error: %s\n",strerror(errno));
  70. exit(1);
  71. }
  72. if (sendto(childfd,send,count,(struct sockaddr*)&to,tolen) != count) {
  73. printf("send to error: %s\n",strerror(errno));
  74. exit(1);
  75. }
  76. while ((count = recvfrom(childfd,&tolen)) > 0) {
  77. if (sendto(childfd,tolen) != count) {
  78. printf("send to client error: %s\n",strerror(errno));
  79. exit(1);
  80. }
  81. }
  82. }
  83. }
  84. }
  85. int main(int argc,char** argv) {
  86. if (argc != 2) {
  87. printf("please add or check <service name>\n");
  88. exit(1);
  89. }
  90.  
  91. struct addrinfo hints;
  92. bzero(&hints,sizeof(struct addrinfo));
  93. hints.ai_flags = AI_PASSIVE;
  94. hints.ai_family = AF_INET;
  95. hints.ai_socktype = SOCK_DGRAM;
  96. hints.ai_protocol = IPPROTO_UDP;
  97.  
  98. struct addrinfo* results;
  99. int err;
  100. if ((err = getaddrinfo(NULL,argv[1],&hints,&results)) != 0) {
  101. printf("getaddrinfo error: %s\n",gai_strerror(err));
  102. exit(1);
  103. }
  104. struct addrinfo* dummy = results;
  105. int sockfd;
  106. for (; dummy != NULL; dummy = dummy->ai_next) {
  107. if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) {
  108. continue;
  109. }
  110. if (ntohs(((struct sockaddr_in*)dummy->ai_addr)->sin_port) >= CHILD_PORT_START) {
  111. printf("Warnning:Dangerous use the port,if have many client,so you should use less than the port try once again\n");
  112. close(sockfd);
  113. exit(1);
  114. }
  115. if (bind(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
  116. break;
  117. }
  118. close(sockfd);
  119. }
  120. server_echo(sockfd);
  121. return 0;
  122. }

客户端代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <netdb.h>
  8.  
  9. #define BUFSIZE 4096
  10.  
  11. void client_echo(int sockfd,struct sockaddr* to,socklen_t tolen) {
  12. char send[BUFSIZE];
  13. ssize_t n;
  14. struct sockaddr_in clientaddr;
  15. const int on = 1;
  16. socklen_t len = sizeof(struct sockaddr_in);
  17. if (setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on)) < 0) {
  18. printf("setsockopt error: %s\n",strerror(errno));
  19. exit(1);
  20. }
  21. while ((n = read(STDIN_FILENO,BUFSIZE)) > 0) {
  22. if (sendto(sockfd,n,to,tolen) != n) {
  23. printf("sendto error: %s\n",strerror(errno));
  24. exit(1);
  25. }
  26. if (recvfrom(sockfd,&len) != n) {
  27. printf("recv from server error: %s\n",strerror(errno));
  28. exit(1);
  29. }
  30. struct sockaddr_in *dummy = (struct sockaddr_in*)to;
  31. dummy->sin_port = clientaddr.sin_port;
  32. if (write(STDOUT_FILENO,n) != n) {
  33. printf("write error: %s\n",strerror(errno));
  34. exit(1);
  35. }
  36. }
  37. }
  38. int main(int argc,char** argv) {
  39. if (argc != 3) {
  40. printf("please add <ip address-host name> <service name or port name>\n");
  41. exit(1);
  42. }
  43.  
  44. struct addrinfo hints;
  45. bzero(&hints,sizeof(struct addrinfo));
  46. hints.ai_flags = AI_ALL;
  47. hints.ai_family = AF_INET;
  48. hints.ai_socktype = SOCK_DGRAM;
  49. hints.ai_protocol = IPPROTO_UDP;
  50.  
  51. struct addrinfo* results;
  52. int err;
  53. if ((err = getaddrinfo(argv[1],argv[2],gai_strerror(err));
  54. exit(1);
  55. }
  56.  
  57. struct addrinfo* dummy = results;
  58. int sockfd;
  59. for (; dummy != NULL; dummy = dummy->ai_next) {
  60. if ((sockfd = socket(dummy->ai_family,dummy->ai_protocol)) < 0) {
  61. continue;
  62. }else {
  63. break;
  64. }
  65. }
  66.  
  67. if (dummy == NULL) {
  68. freeaddrinfo(results);
  69. printf("all socket Failed\n");
  70. exit(1);
  71. }
  72. client_echo(sockfd,dummy->ai_addrlen);
  73. freeaddrinfo(results);
  74. }

猜你在找的Bash相关文章