网络编程Server端 --- Linux版

来源:互联网 发布:php设计模式 编辑:程序博客网 时间:2024/06/09 15:39

http://blog.csdn.net/xiaobin_hlj80/article/details/7172375

之前我们已经编写了一个通用的Socket服务器端程序,我们现在增加对此类操作系统特性的一些code!

大家都知道fork() 只有在Unix/Linux类操作系统才有!因为他们没有线程这一说。他们只有子进程。

要用到fork那么就必须用到 waitpid() !

waitpid函数原型:

#include<sys/types.h> /* 提供类型pid_t的定义 */

#include<sys/wait.h>

pid_twaitpid(pid_tpid, int *status, int options);

参数pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。

参数 status我们设置为NULL。

参数options提供了一些额外的选项来控制waitpid,WNOHANG常量表示,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。

我们希望只有给waitpid()信号时,才使用它!

这时,我们需要另外一个函数sigaction()。

sigaction函数原型:

#include<signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

参数 signum=SIGCHLD时,只有子进程停止或者退出才进行调用。

参数 act是一个指向sigaction结构的指针。

参数 oldact一般废止不用。

我们主要设置结构sigaction的sa_handler、sa_mask和sa_flags三个成员变量即可!

下面是示例:

[cpp] view plaincopyprint?
  1. /**
  2. * Version: 0.2
  3. *
  4. * Description: Add signal
  5. *
  6. */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netdb.h>
  12. #include <arpa/inet.h>
  13. #include <signal.h>
  14. #include <sys/wait.h>
  15. #include <stdlib.h> /* exit declare */
  16. #include <unistd.h> /* fork declare */
  17. #define SERVPORT "2349"
  18. void sigchild_handler()
  19. {
  20. while (waitpid(-1, NULL, WNOHANG) > 0);
  21. }
  22. int main(int argc,char *argv[])
  23. {
  24. struct addrinfo hints, *res;
  25. int status;
  26. int sockfd;
  27. int connFd;
  28. /* struct sockaddr_in cliAddr; Only IPv4 */
  29. struct sockaddr_storage clientAddr;/* both IPv4 and IPv6 */
  30. struct sigaction sa;
  31. int sendSta;
  32. char *msg;
  33. if (argc != 2) {
  34. fprintf(stderr, "Usage: Not found Read File");
  35. return 1;
  36. }
  37. memset(&hints, 0, sizeof(hints));
  38. hints.ai_family = AF_UNSPEC;
  39. hints.ai_socktype = SOCK_STREAM;
  40. hints.ai_flags = AI_PASSIVE;
  41. status = getaddrinfo(NULL, SERVPORT, &hints, &res);
  42. if (status != 0) {
  43. fprintf(stderr, "getaddrinfo, fail!");
  44. return 2;
  45. }
  46. sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  47. bind(sockfd, res->ai_addr, res->ai_addrlen);
  48. listen(sockfd, 5);
  49. printf("======== Please Wait Client =========\n");
  50. /* struct sigaction notes from POSIX:
  51. *
  52. * (1) Routines stored in sa_handler should take a single int as
  53. * their argument although the POSIX standard does not require this.
  54. * (2) The fields sa_handler and sa_sigaction may overlap, and a conforming
  55. * application should not use both simultaneously.
  56. */
  57. sa.sa_handler = sigchild_handler;
  58. sigemptyset(&sa.sa_mask); /* Additional set of signals to be blocked */
  59. /* during execution of signal-catching function. */
  60. sa.sa_flags = SA_RESTART; /* Special flags to affect behavior of signal */
  61. /* SA_RESTART 0x10000000 // Restart syscall on signal return */
  62. if (sigaction(SIGCHLD, &sa, NULL) == -1) {/* SIGCHLD 20 // to parent on child stop or exit */
  63. fprintf(stderr, "sigaction fail!");
  64. exit(3);
  65. }
  66. while(1) { // loop forever!
  67. char ipstr[INET_ADDRSTRLEN];
  68. void *addr;
  69. int len = sizeof(clientAddr);
  70. connFd = accept(sockfd, (struct sockaddr *)&clientAddr, &len);
  71. /* View Client IP */
  72. struct sockaddr_in *ipv4 = (struct sockaddr_in *)&clientAddr;
  73. addr = &(ipv4->sin_addr);
  74. inet_ntop(AF_INET, addr, ipstr, sizeof(ipstr));
  75. printf("client: %s\n", ipstr);
  76. if (!fork()) {
  77. close(sockfd); /* child doesn't need the listener */
  78. /* Copy Data */
  79. msg = "The server simply displays a message!";
  80. sendSta = send(connFd, msg, strlen(msg), 0);
  81. if (sendSta == -1)
  82. fprintf(stderr, "send fail!");
  83. close(connFd);
  84. exit(0);
  85. }
  86. close(connFd);
  87. }
  88. close(sockfd);
  89. return 0;
  90. }

End.

原创粉丝点击