免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2708 | 回复: 3

为什么一个线程结束了整个程序都结束了 [复制链接]

论坛徽章:
0
发表于 2011-05-09 22:21 |显示全部楼层
本帖最后由 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!!!!
怎么设置服务器线程的属性,一个线程结束而整个程序不结束??

论坛徽章:
0
发表于 2011-05-10 08:58 |显示全部楼层
server线程不要用exit()

论坛徽章:
0
发表于 2011-05-10 10:20 |显示全部楼层
本帖最后由 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端也不会退出,看你的需求了

论坛徽章:
0
发表于 2011-05-10 14:34 |显示全部楼层
回复 3# jimmyixy


    多谢,就是这个问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP