为什么一个线程结束了整个程序都结束了

发布于 2022-10-15 07:27:56 字数 14378 浏览 18 评论 0

本帖最后由 butterinsect 于 2011-05-09 22:22 编辑

下面是一个多线程长连接的服务器,客户端发送数据过来,服务器接受数据,然后返回大写的数据

server.c

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <sys/wait.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <pthread.h>
  12. void handleData(int *new_fd);
  13. #define THREAD_NUMBER 5
  14. pthread_t pt[THREAD_NUMBER];
  15. int main(int argc, char **argv)
  16. {
  17.         struct sockaddr_in server_addr;
  18.         struct sockaddr_in client_addr;
  19.         int sockfd, new_fd[THREAD_NUMBER];
  20.         int *arg;
  21.         int portnumber, sin_size;
  22.         if(argc!=2)
  23.         {
  24.                 fprintf(stderr, "the argc is not enough!\n");
  25.         }
  26.         if(atoi(argv[1])<0)
  27.         {
  28.                 fprintf(stderr, "port is not right!\n");
  29.                 exit(1);
  30.         }
  31.         portnumber = atoi(argv[1]);
  32.         if((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1)
  33.         {
  34.                 fprintf(stderr, "the server socket init error:%s\n", strerror(errno));
  35.                 exit(0);
  36.         }
  37.        
  38.         //端口重用
  39.         int on = 1;
  40.         setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  41.         //初始化server_addr
  42.         bzero(&server_addr, sizeof(struct sockaddr_in));
  43.         server_addr.sin_family = AF_INET;
  44.         server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  45.         server_addr.sin_port = htons(portnumber);
  46.         //绑定
  47.         if(bind(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr))==-1)
  48.         {
  49.                 fprintf(stderr, "the server bind error:%s\n", strerror(errno));
  50.                 exit(1);
  51.         }
  52.         if(listen(sockfd, 5)==-1)
  53.         {
  54.                 fprintf(stderr, "the server listen error:%s\n", strerror(errno));
  55.                 exit(1);
  56.         }
  57.         int k = 0;
  58.         while(1)
  59.         {       
  60.                 sin_size = sizeof(struct sockaddr_in);
  61.                 if((new_fd[k]=accept(sockfd, (struct sockaddr*)(&client_addr),&sin_size))==-1)
  62.                 {
  63.                         fprintf(stderr, "the server accept error:%s\n", strerror(errno));
  64.                         continue;
  65.                 }
  66.                 printf("new connection is coming...\n");
  67.                
  68.                
  69.                 if(pthread_create(&pt[k], &attr, (void *)handleData, (void *)&new_fd[k])!=0)
  70.                 {
  71.                         printf("new thread error!\n");
  72.                 }
  73.                 k++;
  74.        
  75.         }
  76.        
  77.         int i;
  78.         for(i=0; i<THREAD_NUMBER; i++)
  79.         {
  80.                 int ret_val = pthread_join(pt[i], NULL);
  81.                 if(ret_val!=0)
  82.                 {
  83.                         printf("pthread_join error!\n");
  84.                         exit(1);
  85.                 }
  86.         }
  87.         close(sockfd);
  88.         return 0;
  89. }
  90. void handleData(int *new_fd)
  91. {
  92.         char *msg;
  93.         while(1)
  94.         {       
  95.                 msg = (char*)malloc(sizeof(char)*1024);
  96.                 memset(msg, 0, 1024);
  97.                 if(read(*new_fd, msg, 1024)==-1)
  98.                 {
  99.                         fprintf(stderr, "the server read error\n");
  100.                 //        exit(1);
  101.                         continue;
  102.                 }
  103.                 int len = strlen(msg);
  104.                 int i;
  105.                 for(i=0; i<len; i++)
  106.                 {
  107.                         if(msg[i]>='a'&&msg[i]<='z')
  108.                                 msg[i]=msg[i]-32;
  109.                 }
  110.                 msg[len]='\0';
  111.                        
  112.                 if(write(*new_fd, msg, 1024)==-1)
  113.                 {
  114.                         fprintf(stderr, "the server write error\n");
  115.                         exit(1);
  116.                 }
  117.                        
  118.         }
  119.         //free(msg);
  120.         pthread_exit(msg);
  121. }

复制代码client.c

  1. /************************************************
  2. *author:butterinsect
  3. *email:yyt5116@163.com
  4. *school:cug
  5. *blog:www://hi.baidu.com/butterinsect
  6. *接受键盘输入,然后把信息发送到服务器
  7. * ************************************************/
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <unistd.h>
  11. #include <errno.h>
  12. #include <string.h>
  13. #include <sys/socket.h>
  14. #include <sys/types.h>
  15. #include <netinet/in.h>
  16. #include <netdb.h>
  17. int main(int argc, char** argv)
  18. {
  19.         int sockfd;
  20.         struct sockaddr_in server_addr;
  21.         struct hostent *host;
  22.         int portnumber, nbytes;
  23.         char msg[1024];
  24.         if(argc!=3)
  25.         {
  26.                 fprintf(stderr, "the argv is not enough 3!\n");
  27.                 exit(1);
  28.         }
  29.         if(inet_aton(argv[1], &server_addr)!=0)
  30.                 host = gethostbyaddr((char *)&server_addr, 4, AF_INET);
  31.         else
  32.                 host = gethostbyname(argv[1]);
  33.         if((portnumber=atoi(argv[2]))<0)
  34.         {
  35.                 fprintf(stderr, "the port of client is error\n");
  36.                 exit(1);
  37.         }
  38.         if((sockfd = socket(AF_INET, SOCK_STREAM, 0))==-1)
  39.         {
  40.                 fprintf(stderr, "client socket init error:%s\n", strerror(errno));
  41.                 exit(1);
  42.         }
  43.         bzero(&server_addr, sizeof(server_addr));
  44.         server_addr.sin_family = AF_INET;
  45.         server_addr.sin_port = htons(portnumber);
  46.         server_addr.sin_addr = *((struct in_addr*)host->h_addr);
  47.        
  48.         if(connect(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr))==-1)
  49.         {
  50.                 fprintf(stderr, "the clinet connect error:%s\n", strerror(errno));
  51.                 exit(1);
  52.         }
  53.        
  54.         while(1)
  55.         {
  56.                 gets(msg);
  57.                 int len = strlen(msg);
  58.                 msg[len]='\0';
  59.                 if(write(sockfd, msg, 1024)==-1)
  60.                 {
  61.                         fprintf(stderr, "the client write error:%s\n", strerror(errno));
  62.                         exit(1);
  63.                 }
  64.                 memset(msg, '0', 1024);
  65.                 if((nbytes=read(sockfd, msg, 1024))==-1)
  66.                 {
  67.                         fprintf(stderr, "the client read error:%s\n", strerror(errno));
  68.                         exit(1);
  69.                 }
  70.                 msg[nbytes]='\0';
  71.                 printf("after tacked:%s\n", msg);
  72.         }
  73.         close(sockfd);
  74.         return 0;
  75. }

复制代码然后运行server
./server 8080

然后运行客户端1
yyt@yyt:~/workspace/apue/tcp/tcpmp$ ./client localhost 8080
hello
after tacked:HELLO
abdc
after tacked:ABDC

然后运行客户端2
yyt@yyt:~/workspace/apue/tcp/tcpmp$ ./client localhost 8080
good
after tacked:GOOD
simida
after tacked:SIMIDA

当ctrl+c结束客户端1时候,服务器也退出了,why!!!!
怎么设置服务器线程的属性,一个线程结束而整个程序不结束??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤千羽 2022-10-22 07:27:56

server线程不要用exit()

影子的影子 2022-10-22 07:27:56

本帖最后由 jimmyixy 于 2011-05-10 10:35 编辑

客户端ctl c 是向服务器发送了SIGPIPE信号,服务器端觉得客户端写异常直接退出

  1. ret = read(*new_fd, msg, 1024);
  2.                 if(ret == 0){
  3.                         shutdown(*new_fd, SHUT_RD);
  4.                 close(*new_fd);
  5.                         printf("client close!\n");
  6.                         return ;
  7.                         }

复制代码这样是可以的
当所有客户端都断开时server端也不会退出,看你的需求了

蹲在坟头点根烟 2022-10-22 07:27:56

回复 3# jimmyixy

    多谢,就是这个问题

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文