linux C TCP UDP server 接收多个客户端同时连接的多线程
我想做一个的TCP UDP server端,实现这样一个功能:每当一个客户端连接过来时,创建一个单独的线程去处理这个客户端。
现在测试发现,当多个TCP客户端连接进来的时候,只会保留最新的一个客户端线程通信,先连接进来的客户端线程都没在运行也无法发送数据?怎么回事?本人小白,请多指教。以下是代码:
#include ..一些头文件,省略。
#define LOCAL_IP "192.168.1.66"
#define LOCAL_PORT 8888
struct pthread_arg//供线程使用的参数
{
char protocol;// protocol =='U'为udp连接 ; protocol == 'T'则为tcp连接;
int fd;
struct sockaddr_in sock;
int num;
};
static void *deal_send_pth(void *arg)
{
struct pthread_arg *r=( struct pthread_arg *)arg;
printf("pth%d running...\n",r->num);
}
main()
{
int i;
struct sockaddr_in server_addr, client_addr;
struct pthread_arg ptr_arg;//供线程使用的参数
fd_set fdset;
pthread_t pthid;
int tcp_socketfd, tcp_connectfd, udp_connectfd, maxfd;
int client_len;
char local_port[32], local_ip[32];
int reuse = 1;//进程结束后端口允许重用,否则在调试程序时得等系统回收端口,浪费时间
void *retval;
//--------------------- TCP ----------------------------------------------------------
if((tcp_socketfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("fail to socket!!\n");
exit(-1);
}
printf("socket success!!\n");
setsockopt(tcp_socketfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
sprintf(local_ip, "%s", LOCAL_IP);
server_addr.sin_addr.s_addr = inet_addr(local_ip);
printf("[server ip = %s]\n", local_ip);
sprintf(local_port, "%d", LOCAL_PORT);
server_addr.sin_port = htons(atoi(local_port));
printf("[tcp server port = %s]\n", local_port);
if(bind(tcp_socketfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("fail to bind!!");
exit(-1);
}
if(listen(tcp_socketfd, 5) < 0)
{
perror("fail to listen!!");
exit(-1);
}
//--------------------- UDP ---------------------------------------------------------------------
server_addr.sin_port = htons(atoi(local_port));
printf("[udp server port = %s]\n", local_port);
if((udp_connectfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error : udp fail to socket!!\n");
exit(-1);
}
if(bind(udp_connectfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("Error : udp fail to bind!!\n");
exit(-1);
}
maxfd = (tcp_connectfd > udp_connectfd ? tcp_connectfd : udp_connectfd);
while(1)
{
struct sockaddr_in client_addr;
FD_ZERO(&fdset);
FD_SET(tcp_socketfd, &fdset);
FD_SET(udp_connectfd, &fdset);
if(select(maxfd+1, &fdset, NULL, NULL, NULL)< 0)
{
perror("Error: select error!!\n");
exit(-1);
}
//tcp连接-------------------------------
//为每一个tcp客户端创建独立的处理线程,线程处理函数为deal_send_pth,参数为ptr_arg
if(FD_ISSET(tcp_socketfd, &fdset))
{
printf("----------pass 2 -------------\n");
sleep(1);
//循环接受客户端的链接请求
client_len = sizeof(client_addr);
if((tcp_connectfd = accept(tcp_socketfd, (struct sockaddr *)&client_addr, (socklen_t *)&(client_len))) < 0)
{
perror("fail to accept!!");
return -1;
}
ptr_arg.protocol = 'T';
ptr_arg.fd = tcp_connectfd;
memcpy((char *)&ptr_arg.sock, (const char *)&client_addr,sizeof(struct sockaddr_in));
ptr_arg.num = i;
if(pthread_create(&pthid, NULL, deal_send_pth, (void *)&ptr_arg) < 0)
{
perror("fail to pthread_create!!");
return -1;
}
pthread_detach(pthid);//回收线程、非阻塞
i++;
}
}
}