linux基础编程 套接字socket 完整的服务器端多线程socket程序【转】
转自:http://blog.csdn.net/ghostyu/article/details/7737203
此段程序来自我的一个项目中,稍微做了些修改,运行稳定,客户端程序比较简单所以未编写,可以用socket调试工具测试此段代码 费话不多说,直接上代码 [cpp] view plain copy #include<stdlib.h> #include<stdio.h> #include<string.h> #include<errno.h> #include<netdb.h> #include<sys/types.h> #include<netinet/in.h> #include<sys/socket.h> #include<sys/wait.h> #include<unistd.h> #include<pthread.h> #include<fcntl.h> #define __DEBUG #ifdef __DEBUG #define DBG(fmt,args...) fprintf(stdout, fmt, ##args) #else #define DBG(fmt,args...) #endif #define ERR(fmt,args...) fprintf(stderr, fmt, ##args) /* isStreamQuit == 0 :Start isStreamQuit == 1 :Client Quit isStreamQuit ==-1 :App Quit */ static int isStreamQuit = 0; static int gStreamServerFd = -1; int gStreamClientFd; #define PORT_SOCKET 9000 //server监听端口 #define RECV_BUF_MAX_LEN 512 #define TIME_WAIT 200000 /*200ms*/ /* socket发送函数 */ int ScketSend(unsigned char *buf,unsigned int len) { int ret = 0; if(gStreamClientFd <= 0) return -1; ret = send(gStreamClientFd,buf,len,0); if(ret <= 0 ){ return -1; }else if(ret == len){ return 0; } while(ret < len){ ret += send(gStreamClientFd,buf+ret,len-ret,0); } return 0; } /* socket连接线程,阻塞等待客户端的连接, 连接后循环处理客户端发来的数据, 这里只能连接一个客户端,稍加修改,就可以支持多客户端连接 */ void *SocketThread(void *arg) { fd_set SockRead; struct timeval TimeOut; int ret; struct sockaddr clientAddr; unsigned char *rcvBuf = (unsigned char *)malloc(RECV_BUF_MAX_LEN); socklen_t len; len = sizeof(clientAddr); while(1){ int rcvLen; /*阻塞等待客户端连接*/ gStreamClientFd = accept(gStreamServerFd, &clientAddr, &len); if(gStreamClientFd == -1){ ERR("ERROR in stream accept: %s\n",strerror(errno)); /*add errno handler here,in some case,the error is not fatal*/ /*code here*/ break; } /*isStreamQuit == -1,is the siganl to quit*/ if(isStreamQuit != -1){ isStreamQuit = 0; } DBG("accep a stream client\n"); /*客户端已连接,循环处理*/ while(isStreamQuit==0){ FD_ZERO(&SockRead); FD_SET(gStreamClientFd,&SockRead); TimeOut.tv_sec = 0; TimeOut.tv_usec = TIME_WAIT; /* 200ms超时判断是否有数据接收,有则接收,没有继续循环, 总是让程序不能一直阻塞在这里 */ ret = select(gStreamClientFd+1,&SockRead,NULL,NULL,&TimeOut); if(ret == -1){ ERR("ERROR in select\n"); break; }else if(ret == 0){ continue; } /*接收客户端发来的数据*/ rcvLen = recv(gStreamClientFd,rcvBuf,RECV_BUF_MAX_LEN,0); if(rcvLen < 0){ ERR("ERROR in stream accept: %s\n",strerror(errno)); /*add errno handler here,in some case,the error is not fatal*/ /*code here*/ isStreamQuit = 1; break; }else if(rcvLen == 0){ DBG("stream client close\n"); /*code here*/ isStreamQuit = 1; break; } DBG("rcvLen: %d,rcvBuf: %s\n",rcvLen,rcvBuf); memset(rcvBuf,0,RECV_BUF_MAX_LEN); } DBG("Close Stream Socket\n"); close(gStreamClientFd); /*OTHER Error or App Quit*/ if(isStreamQuit == -1){ break; } } DBG("SocketThread exit\n"); free(rcvBuf); close(gStreamServerFd); pthread_exit(NULL); } /* socket连接初始化 */ int SocketInit() { struct sockaddr_in server; pthread_t tStreamSocketThr; /*创建socket*/ gStreamServerFd = socket(AF_INET,SOCK_STREAM,0); if(gStreamServerFd == -1 ){ ERR("ERROR in create Stream Socket!\n"); return -1; } memset(&server,0,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT_SOCKET); server.sin_addr.s_addr = htonl(INADDR_ANY); /*绑定监听端口*/ if(bind(gStreamServerFd ,(struct sockaddr*)&server,sizeof(server))== -1){ ERR("ERROR in bind Stream Socket: %s\n",strerror(errno)); return -1; } /*开始监听*/ if( listen(gStreamServerFd, 5) == -1){ ERR("ERROR in listen Stream Socket: %s\n",strerror(errno)); return -1; } /*创建socket连接线程,用来处理监听的结果,比如有客户端连接等*/ pthread_create(&tStreamSocketThr,NULL,SocketThread,NULL); /*release thread resource,so we not use pthread_join to waitting*/ pthread_detach(tStreamSocketThr); return 0; } #if 1 int main() { if(SocketInit() == -1){ return -1; } while(1){ sleep(2); } /*notice to exit*/ isStreamQuit = -1; sleep(1); if(gStreamServerFd){ close(gStreamServerFd); } DBG("SUCCESS in ConnectManageExit\n"); } #endif 运行结果 [cpp] view plain copy [root@localhost src]# ./socket_connect accep a stream client rcvLen: 7,rcvBuf: helle 1 Close Stream Socket accep a stream client rcvLen: 7,rcvBuf: hello 2 Close Stream Socket accep a stream client rcvLen: 7,rcvBuf: hello 3 rcvLen: 7,rcvBuf: hello 4 rcvLen: 7,rcvBuf: helle 5 Close Stream Socket
【作者】sky
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.