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

时间:2023-03-09 08:46:18
linux基础编程 套接字socket 完整的服务器端多线程socket程序【转】

转自:http://blog.****.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 = ;
static int gStreamServerFd = -;
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 = ;
if(gStreamClientFd <= )
return -;
ret = send(gStreamClientFd,buf,len,);
if(ret <= ){
return -;
}else if(ret == len){
return ;
}
while(ret < len){
ret += send(gStreamClientFd,buf+ret,len-ret,);
}
return ;
} /*
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(){ int rcvLen;
/*阻塞等待客户端连接*/
gStreamClientFd = accept(gStreamServerFd, &clientAddr, &len);
if(gStreamClientFd == -){
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 != -){
isStreamQuit = ;
}
DBG("accep a stream client\n");
/*客户端已连接,循环处理*/
while(isStreamQuit==){
FD_ZERO(&SockRead);
FD_SET(gStreamClientFd,&SockRead);
TimeOut.tv_sec = ;
TimeOut.tv_usec = TIME_WAIT;
/*
200ms超时判断是否有数据接收,有则接收,没有继续循环,
总是让程序不能一直阻塞在这里
*/
ret = select(gStreamClientFd+,&SockRead,NULL,NULL,&TimeOut);
if(ret == -){
ERR("ERROR in select\n");
break;
}else if(ret == ){
continue;
}
/*接收客户端发来的数据*/
rcvLen = recv(gStreamClientFd,rcvBuf,RECV_BUF_MAX_LEN,);
if(rcvLen < ){
ERR("ERROR in stream accept: %s\n",strerror(errno));
/*add errno handler here,in some case,the error is not fatal*/
/*code here*/
isStreamQuit = ;
break;
}else if(rcvLen == ){
DBG("stream client close\n");
/*code here*/
isStreamQuit = ;
break;
}
DBG("rcvLen: %d,rcvBuf: %s\n",rcvLen,rcvBuf); memset(rcvBuf,,RECV_BUF_MAX_LEN);
}
DBG("Close Stream Socket\n");
close(gStreamClientFd); /*OTHER Error or App Quit*/
if(isStreamQuit == -){
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,);
if(gStreamServerFd == - ){
ERR("ERROR in create Stream Socket!\n");
return -;
}
memset(&server,,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))== -){
ERR("ERROR in bind Stream Socket: %s\n",strerror(errno));
return -;
}
/*开始监听*/
if( listen(gStreamServerFd, ) == -){
ERR("ERROR in listen Stream Socket: %s\n",strerror(errno));
return -;
}
/*创建socket连接线程,用来处理监听的结果,比如有客户端连接等*/
pthread_create(&tStreamSocketThr,NULL,SocketThread,NULL);
/*release thread resource,so we not use pthread_join to waitting*/
pthread_detach(tStreamSocketThr);
return ;
} #if 1
int main()
{
if(SocketInit() == -){
return -;
}
while(){
sleep();
} /*notice to exit*/
isStreamQuit = -;
sleep();
if(gStreamServerFd){
close(gStreamServerFd);
}
DBG("SUCCESS in ConnectManageExit\n");
}
#endif 运行结果 [cpp] view plain copy [root@localhost src]# ./socket_connect
accep a stream client
rcvLen: ,rcvBuf: helle
Close Stream Socket
accep a stream client
rcvLen: ,rcvBuf: hello
Close Stream Socket
accep a stream client
rcvLen: ,rcvBuf: hello
rcvLen: ,rcvBuf: hello
rcvLen: ,rcvBuf: helle
Close Stream Socket