如何唤醒socket被阻塞的函数

发表于:2013-2-18 10:27

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:懒惰的肥兔    来源:51Testing软件测试网采编

#
Linux
分享:

  最近项目遇到一个问题,程序退出的时候资源没有正常释放。经过调试发现,原来是网络线程一直阻塞,导致一些必要的资源没有被释放,写了几个简单的测试程序调试了一下才明白,原来在Linux下直接close socket的文件描述符,并不会使程序中调用的一些阻塞式的socket函数(比如 read、recvfrom 等)退出阻塞,从而导致无法正常释放资源。简化示例如下。

  下面是一个简化的UDP服务程序,首先创建socket对象,然后开启服务线程,将客户端发送过来的数据包回发给客户端。当用户在shell中敲入两次回车后,程序退出。我们来观察一下程序退出后,socket服务线程在怎样的情况下可以正常退出。

  1. #include <stdio.h>  
  2. #include <sys/types.h>  
  3. #include <sys/socket.h>  
  4. #include <linux/in.h>  
  5. #include <string.h>  
  6. #include <pthread.h>  
  7.   
  8. #define SERVER_PORT 8888  
  9. #define BUFFER_LEN  256  
  10.   
  11. int g_Exit = 0;  
  12.   
  13. void *service( void* arg )  
  14. {  
  15.     char buff[BUFFER_LEN];  
  16.     struct sockaddr clientAddr;  
  17.     int socklen = sizeof(clientAddr);  
  18.     int recvbytes;  
  19.     int socketfd = *((int *)arg);  
  20.   
  21.     printf("OK, Enter Service!\n");  
  22.   
  23.     while(!g_Exit)  
  24.     {  
  25.         recvbytes = recvfrom(socketfd,buff,BUFFER_LEN,0,&clientAddr,&socklen);  
  26.   
  27.         sendto(socketfd,buff,recvbytes,0,&clientAddr,socklen);  
  28.     }  
  29.   
  30.     printf("OK, Service Thread Exit!\n");  
  31.   
  32.     pthread_exit(NULL);;  
  33. }  
  34.   
  35. int main( int argc,char * argv[] )  
  36. {  
  37.     int fd;  
  38.     void *status;  
  39.     struct sockaddr_in serverAddr;  
  40.     pthread_t thr;  
  41.     pthread_attr_t attr;  
  42.   
  43.     fd = socket(AF_INET,SOCK_DGRAM,0);  
  44.   
  45.     memset(&serverAddr,0,sizeof(serverAddr));  
  46.   
  47.     serverAddr.sin_family = AF_INET;  
  48.     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  49.     serverAddr.sin_port = htons(SERVER_PORT);  
  50.   
  51.     bind(fd,(struct sockaddr *)&serverAddr,sizeof(serverAddr));  
  52.     // create service thread  
  53.     pthread_attr_init(&attr);  
  54.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);  
  55.     if( pthread_create(&thr,&attr,service,(void *)&fd ) )  
  56.     {  
  57.         printf("pthread_create fail!\n");  
  58.         return -1;  
  59.     }  
  60.     // Free attribute  
  61.     pthread_attr_destroy(&attr);  
  62.   
  63.     // wait user control exit 
  64.     getchar();  
  65.     getchar();  
  66.   
  67.     g_Exit = 1;      
  68.   
  69.     printf("OK, Waiting For Thread Exit...!\n");  
  70.   
  71.     close(fd);
  72.   
  73.     // wait for thread exit
  74.     pthread_join(thr, &status);
  75. printf("OK, Exit Main Process !\n");
  76.     return 0;  
  77. }

  上述程序,当用户敲两次回车后,显示结果如下:

  可以看到,没有打出主进程和服务线程的退出信息,无论是主进程还是服务线程都没有正常退出,由此可见,直接close socket句柄,并不能使 recvfrom 函数退出阻塞。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号