多线程

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <pthread.h>
  6. #include <netinet/ip.h>
  7. #include <arpa/inet.h>
  8. #include <sys/un.h>
  9. #include <ctype.h>
  10. #include "wrap.h"
  11. #include <signal.h>
  12. #include <sys/wait.h>
  13. #define LISTEN_BACKLOG 50
  14. #define EXIT_FAILURE 1
  15. #define SERVICE_PORT 2222
  16. void* thread_func(void* arg){
  17. /*处理请求*/
  18. int cfd=(int)arg;
  19. char buffer[BUFSIZ];
  20. int ret=read(cfd,buffer,BUFSIZ);
  21. write(STDOUT_FILENO,buffer,ret);
  22. for(int i=0;i<ret;i++){
  23. buffer[i]=toupper(buffer[i]);
  24. }
  25. write(cfd,buffer,ret);
  26. close(cfd); //关闭连接套接字
  27. return NULL;
  28. }
  29. /* 用于其他线程回收线程 */
  30. void* garbage_collection(void* arg){
  31. pthread_t *pid=(pthread_t*)arg;
  32. pthread_join(*pid,NULL);
  33. pthread_detach(pthread_self());
  34. return NULL;
  35. }
  36. int main(int argc,char *argv[]){
  37. int lfd,cfd;
  38. pthread_t tid,gid;
  39. struct sockaddr_in srv_addr,client_addr;
  40. char client_ip_addr[20];
  41. socklen_t client_addr_size;
  42. /* 创建套接字 */
  43. lfd=Socket(AF_INET,SOCK_STREAM,0);
  44. /* 创建服务器地址 */
  45. memset(&srv_addr,0,sizeof(struct sockaddr_in));
  46. srv_addr.sin_family=AF_INET;
  47. srv_addr.sin_port=htons(SERVICE_PORT);
  48. srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  49. /*端口复用*/
  50. int optval=1;
  51. setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&optval,sizeof(optval));
  52. /* 绑定 */
  53. Bind(lfd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
  54. /* 设置监听上限 */
  55. Listen(lfd,LISTEN_BACKLOG);
  56. client_addr_size=sizeof(struct sockaddr_in);
  57. while(1){
  58. /* 等待连接 */
  59. cfd=Accept(lfd,(struct sockaddr*)&client_addr,&client_addr_size);
  60. //将IP地址转换为点分十进制
  61. inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr));
  62. printf("new client coming! ip: %s port %d \n",client_ip_addr,ntohs(client_addr.sin_port));
  63. /*创建线程*/
  64. int create_ret=pthread_create(&tid,NULL,thread_func,(void*)cfd);
  65. if(create_ret!=0) perr_exit("join error");
  66. pthread_create(&gid,NULL,garbage_collection,(void*)&tid);
  67. continue;
  68. }
  69. #ifdef DEBUGLOG
  70. printf("client info: ip: %s port %d \n",
  71. inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr))
  72. ,client_addr.sin_port);
  73. #endif
  74. return 0;
  75. }

多进程

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <pthread.h>
  6. #include <netinet/ip.h>
  7. #include <arpa/inet.h>
  8. #include <sys/un.h>
  9. #include <ctype.h>
  10. #include "wrap.h"
  11. #include <signal.h>
  12. #include <sys/wait.h>
  13. #define LISTEN_BACKLOG 50
  14. #define EXIT_FAILURE 1
  15. #define SERVICE_PORT 2222
  16. void Sig_handle(int signo){
  17. if(signo==SIGCHLD){
  18. pid_t ret;
  19. int state;
  20. while((ret=waitpid(-1,&state,WNOHANG))!=-1){
  21. if(ret!=0 && WIFEXITED(state)){
  22. printf("child %d finish the task with exit state %d\n",ret,WEXITSTATUS(state));
  23. }
  24. }
  25. }
  26. }
  27. int main(int argc,char *argv[]){
  28. int lfd,cfd;
  29. pid_t pid;
  30. struct sockaddr_in srv_addr,client_addr;
  31. char client_ip_addr[20];
  32. socklen_t client_addr_size;
  33. /* 信号相关 */
  34. sigset_t set,oldset;
  35. sigemptyset(&set);
  36. sigaddset(&set,SIGCHLD);
  37. /* 创建套接字 */
  38. lfd=Socket(AF_INET,SOCK_STREAM,0);
  39. /* 创建服务器地址 */
  40. memset(&srv_addr,0,sizeof(struct sockaddr_in));
  41. srv_addr.sin_family=AF_INET;
  42. srv_addr.sin_port=htons(SERVICE_PORT);
  43. srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  44. /* 绑定 */
  45. Bind(lfd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
  46. /* 设置监听上限 */
  47. Listen(lfd,LISTEN_BACKLOG);
  48. client_addr_size=sizeof(struct sockaddr_in);
  49. while(1){
  50. /* 等待连接 */
  51. cfd=Accept(lfd,(struct sockaddr*)&client_addr,&client_addr_size);
  52. printf("new client coming! ip: %s port %d \n",
  53. inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr))
  54. ,client_addr.sin_port);
  55. // sigprocmask(SIG_BLOCK,&set,&oldset);
  56. pid=Fork();
  57. if(pid==0){//child
  58. close(lfd); //关闭监听套接字
  59. /*处理请求*/
  60. char buffer[BUFSIZ];
  61. int ret=read(cfd,buffer,BUFSIZ);
  62. write(STDOUT_FILENO,buffer,ret);
  63. for(int i=0;i<ret;i++){
  64. buffer[i]=toupper(buffer[i]);
  65. }
  66. write(cfd,buffer,ret);
  67. close(cfd); //关闭连接套接字
  68. }else if(pid>0){
  69. close(cfd);
  70. struct sigaction act;
  71. /*信号回收子进程*/
  72. sigemptyset(&act.sa_mask);
  73. act.sa_flags=0;
  74. act.sa_handler=Sig_handle;
  75. int sig_ret=sigaction(SIGCHLD,&act,NULL);
  76. if(sig_ret!=0)
  77. perr_exit("sigaction");
  78. // sigprocmask(SIG_SETMASK,&oldset,NULL);
  79. continue;
  80. }
  81. }
  82. #ifdef DEBUGLOG
  83. printf("client info: ip: %s port %d \n",
  84. inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr))
  85. ,client_addr.sin_port);
  86. #endif
  87. return 0;
  88. }