linux基础编程 套接字socket 完整的服务器端多线程socket程序

[cpp]  view plain copy
  1. #include<stdlib.h>   
  2. #include<stdio.h>   
  3. #include<string.h>   
  4. #include<errno.h>   
  5. #include<netdb.h>   
  6. #include<sys/types.h>   
  7. #include<netinet/in.h>   
  8. #include<sys/socket.h>   
  9. #include<sys/wait.h>   
  10. #include<unistd.h>   
  11. #include<pthread.h>   
  12. #include<fcntl.h>  
  13.   
  14. #define __DEBUG  
  15. #ifdef __DEBUG  
  16. #define DBG(fmt,args...) fprintf(stdout,  fmt,  ##args)  
  17. #else  
  18. #define DBG(fmt,args...)  
  19. #endif  
  20. #define ERR(fmt,args...) fprintf(stderr,  fmt,  ##args)  
  21.   
  22. /* 
  23. isStreamQuit == 0 :Start 
  24. isStreamQuit == 1 :Client Quit 
  25. isStreamQuit ==-1 :App Quit 
  26. */  
  27. static int isStreamQuit    = 0;  
  28. static int gStreamServerFd = -1;  
  29. int gStreamClientFd;  
  30.   
  31. #define PORT_SOCKET          9000   //server监听端口  
  32. #define RECV_BUF_MAX_LEN     512  
  33. #define TIME_WAIT            200000     /*200ms*/  
  34.   
  35. /* 
  36. socket发送函数 
  37.  */  
  38. int ScketSend(unsigned char *buf,unsigned int len)  
  39. {  
  40.       
  41.     int ret = 0;  
  42.     if(gStreamClientFd <= 0)  
  43.         return -1;  
  44.     ret = send(gStreamClientFd,buf,len,0);  
  45.     if(ret <= 0 ){  
  46.         return -1;  
  47.     }else if(ret == len){  
  48.         return 0;  
  49.     }  
  50.     while(ret < len){  
  51.         ret += send(gStreamClientFd,buf+ret,len-ret,0);  
  52.     }  
  53.     return 0;  
  54. }  
  55.   
  56. /* 
  57. socket连接线程,阻塞等待客户端的连接, 
  58. 连接后循环处理客户端发来的数据, 
  59. 这里只能连接一个客户端,稍加修改,就可以支持多客户端连接 
  60. */  
  61. void *SocketThread(void *arg)  
  62. {  
  63.     fd_set SockRead;  
  64.     struct timeval TimeOut;  
  65.     int ret;  
  66.     struct sockaddr clientAddr;   
  67.     unsigned char *rcvBuf = (unsigned char *)malloc(RECV_BUF_MAX_LEN);  
  68.       
  69.     socklen_t  len;  
  70.     len = sizeof(clientAddr);  
  71.     while(1){  
  72.           
  73.         int rcvLen;  
  74.         /*阻塞等待客户端连接*/  
  75.         gStreamClientFd = accept(gStreamServerFd, &clientAddr, &len);  
  76.         if(gStreamClientFd == -1){  
  77.             ERR("ERROR in stream accept: %s\n",strerror(errno));  
  78.             /*add errno handler here,in some case,the error is not fatal*/  
  79.             /*code here*/  
  80.             break;  
  81.         }  
  82.         /*isStreamQuit == -1,is the siganl to quit*/  
  83.         if(isStreamQuit != -1){  
  84.             isStreamQuit = 0;  
  85.         }  
  86.         DBG("accep a stream client\n");  
  87.         /*客户端已连接,循环处理*/  
  88.         while(isStreamQuit==0){  
  89.             FD_ZERO(&SockRead);  
  90.             FD_SET(gStreamClientFd,&SockRead);  
  91.             TimeOut.tv_sec = 0;  
  92.             TimeOut.tv_usec = TIME_WAIT;  
  93.             /* 
  94.             200ms超时判断是否有数据接收,有则接收,没有继续循环, 
  95.             总是让程序不能一直阻塞在这里 
  96.             */  
  97.             ret = select(gStreamClientFd+1,&SockRead,NULL,NULL,&TimeOut);  
  98.             if(ret == -1){  
  99.                 ERR("ERROR in select\n");  
  100.                 break;  
  101.             }else if(ret == 0){  
  102.                 continue;  
  103.             }  
  104.             /*接收客户端发来的数据*/  
  105.             rcvLen = recv(gStreamClientFd,rcvBuf,RECV_BUF_MAX_LEN,0);  
  106.             if(rcvLen < 0){  
  107.                 ERR("ERROR in stream accept: %s\n",strerror(errno));  
  108.                 /*add errno handler here,in some case,the error is not fatal*/  
  109.                 /*code here*/  
  110.                 isStreamQuit = 1;  
  111.                 break;  
  112.             }else if(rcvLen == 0){  
  113.                 DBG("stream client close\n");  
  114.                 /*code here*/  
  115.                 isStreamQuit = 1;  
  116.                 break;  
  117.             }  
  118.             DBG("rcvLen: %d,rcvBuf: %s\n",rcvLen,rcvBuf);  
  119.   
  120.             memset(rcvBuf,0,RECV_BUF_MAX_LEN);  
  121.         }  
  122.         DBG("Close Stream Socket\n");  
  123.         close(gStreamClientFd);  
  124.           
  125.         /*OTHER Error or App Quit*/  
  126.         if(isStreamQuit == -1){  
  127.             break;  
  128.         }  
  129.   
  130.     }  
  131.     DBG("SocketThread exit\n");  
  132.     free(rcvBuf);  
  133.     close(gStreamServerFd);  
  134.     pthread_exit(NULL);  
  135. }  
  136.   
  137. /* 
  138. socket连接初始化 
  139. */  
  140. int SocketInit()  
  141. {  
  142.     struct sockaddr_in server;  
  143.     pthread_t tStreamSocketThr;  
  144.     /*创建socket*/  
  145.     gStreamServerFd = socket(AF_INET,SOCK_STREAM,0);   
  146.     if(gStreamServerFd == -1 ){  
  147.         ERR("ERROR in create Stream Socket!\n");  
  148.         return -1;  
  149.     }  
  150.     memset(&server,0,sizeof(server));  
  151.     server.sin_family = AF_INET;  
  152.     server.sin_port = htons(PORT_SOCKET);  
  153.     server.sin_addr.s_addr = htonl(INADDR_ANY);  
  154.     /*绑定监听端口*/  
  155.     if(bind(gStreamServerFd ,(struct sockaddr*)&server,sizeof(server))== -1){  
  156.         ERR("ERROR in bind Stream Socket: %s\n",strerror(errno));  
  157.         return -1;  
  158.     }  
  159.     /*开始监听*/  
  160.     if( listen(gStreamServerFd, 5) == -1){  
  161.         ERR("ERROR in listen Stream Socket: %s\n",strerror(errno));  
  162.         return -1;  
  163.     }  
  164.     /*创建socket连接线程,用来处理监听的结果,比如有客户端连接等*/  
  165.     pthread_create(&tStreamSocketThr,NULL,SocketThread,NULL);  
  166.     /*release thread resource,so we not use pthread_join to waitting*/  
  167.     pthread_detach(tStreamSocketThr);  
  168.     return 0;  
  169. }  
  170.   
  171. #if 1  
  172. int main()  
  173. {  
  174.     if(SocketInit() == -1){  
  175.         return -1;  
  176.     }  
  177.     while(1){  
  178.         sleep(2);  
  179.     }  
  180.       
  181.     /*notice to exit*/  
  182.     isStreamQuit = -1;  
  183.     sleep(1);  
  184.     if(gStreamServerFd){  
  185.         close(gStreamServerFd);  
  186.     }  
  187.     DBG("SUCCESS in ConnectManageExit\n");  
  188. }  
  189. #endif   

运行结果

[cpp]  view plain copy
  1. [root@localhost src]# ./socket_connect  
  2. accep a stream client  
  3. rcvLen: 7,rcvBuf: helle 1  
  4. Close Stream Socket  
  5. accep a stream client  
  6. rcvLen: 7,rcvBuf: hello 2  
  7. Close Stream Socket  
  8. accep a stream client  
  9. rcvLen: 7,rcvBuf: hello 3  
  10. rcvLen: 7,rcvBuf: hello 4  
  11. rcvLen: 7,rcvBuf: helle 5  
  12. Close Stream Socket  

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值