欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

socket多线程通信(一个服务器对多个客户端)

程序员文章站 2022-06-06 09:34:48
...

socket多线程通信(一个服务器对多个客户端)

1.服务器端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#define PORT 8888
#define MAX_NUM_CLIENT 10

struct pthread_data{
    struct sockaddr_in client_addr;
    int sock_fd;
};
void *server_handle(void * arg);

int client_fds[MAX_NUM_CLIENT];

int main()
{
    int sock_fd;
    struct sockaddr_in serv_addr;
    int client_fd;
    struct sockaddr_in client_add;
    char buff[1024];
    socklen_t len;
    int num=0;
	int i;

    for(i=0;i<MAX_NUM_CLIENT;i++)
	{
		client_fds[i]=0;
	}
    //创建socket连接
    sock_fd=socket(AF_INET,SOCK_STREAM,0);
    if(sock_fd==-1)
    {
        perror("create socket error!");
        return 0;
    }
    else
    {
        printf("Success to create socket %d\n",sock_fd);
    }

    //设置server地址结构
    bzero(&serv_addr,sizeof(serv_addr));    //初始化结构占用内存
    serv_addr.sin_family=AF_INET;    //设置传输层类型IPv4
    serv_addr.sin_port=htons(PORT);    //设置端口号
    serv_addr.sin_addr.s_addr=htons(INADDR_ANY);    //设置服务器IP地址
    bzero(&(serv_addr.sin_zero),8);

    //绑定端口
    if(bind(sock_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))!=0)
    {
         printf("bind address fail %d\n",errno);
         close(sock_fd);
         return 0;
    }
    else
    {
         printf("Success to bind address!\n");
    }

    //监听端口
    if(listen(sock_fd,MAX_NUM_CLIENT!=0))
    {
        perror("listen socket error!\n");
        close(sock_fd);
        return 0;
    }
    else
    {
        printf("Success to listen\n");
    }

    //创建连接客户端的对应套接字
    len=sizeof(client_add);

    printf("listening...\n");
    while(1)
	{
        //接收客户端连接
		client_fd=accept(sock_fd,(struct sockaddr*)&client_add,&len);
        if(client_fd<=0)
        {
            perror("accept error!");
            continue;
        }
		else
		{
			//遍历所有已连接的客户端
			for(i=0;i<MAX_NUM_CLIENT;i++)
			{
			    if(client_fds[i]==0)
				{
					client_fds[i]=client_fd;
					pthread_t tid;
					//创建多线程
			        if(pthread_create(&tid,NULL,server_handle,&client_fd))    
                    {
                        perror("Fail to create thread");
						break;
                    }
					printf("client_fds[%d] join in!\n",i);
					num++;
					if(num==MAX_NUM_CLIENT-1)
				    {
					    printf("client full!\n");
				    }
					break;
				}
				
				
			}
		}
    }
    close(client_fd);
    close(sock_fd);
    return 0;
}

//每个线程对应一个客户端
void *server_handle(void *arg)
{
    int *fd = arg;
	int client_fd;
	client_fd=*fd;
    int i,n,num;
    char recvbuf[1024];
    char sendbuf[1024];
    //找到自己的客户端序号
	for(i=0;i<MAX_NUM_CLIENT;i++)
    {
	    if(client_fds[i]==client_fd)
	    {
			num=i;
		}
	}
	//不断接收客户端信息
    while((n=recv(client_fd, recvbuf, sizeof(recvbuf), 0))>0)
	{	 
        printf("client_fds[%d]:%s\n",num,recvbuf);
		//如果客户端发出quit命令,则断开连接,结束线程
		if(strcmp(recvbuf,"quit") == 0)
		{
			for(i=0;i<MAX_NUM_CLIENT;i++)
            { 
				if(client_fds[i]==client_fd)
				{
					send(client_fds[i], sendbuf, sizeof(sendbuf), 0);
					client_fds[i]=0;
					printf("client_fds[%d] has been left!\n",i);
					sprintf(sendbuf, "client_fds[%d] has been left!\n", i);
				}
		    }
			for(i=0;i<MAX_NUM_CLIENT;i++)
            { 
				if(client_fds[i]!=0)
			         send(client_fds[i], sendbuf, sizeof(sendbuf), 0);
		    }
            break;
        }
		//向所有客户端发送此客户端发的信息
		sprintf(sendbuf,"client_fds[%d]:%s\n",num,recvbuf);
		for(i=0;i<MAX_NUM_CLIENT;i++)
        {
			if(client_fds[i]!=0)
			    send(client_fds[i], sendbuf, sizeof(sendbuf), 0);
		}
        memset(recvbuf,0,sizeof(recvbuf));
    }
	
    close(client_fd);
    pthread_exit(0);
}

2.客户端

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#define EHCO_PORT 8888

int sock_fd;

void *client_handle(void *arg)
{
	//发送并接收缓冲的数据
	char buff[1024];
    while(1)
    {
        gets(buff);
        send(sock_fd,buff,1024,0);
    }
	
}

int main()
{

    struct sockaddr_in serv_addr;
    
    char recv_buff[1024];
    int n,i;
    pthread_t thread;
	
    //创建socket
    sock_fd=socket(AF_INET,SOCK_STREAM,0);
    if(sock_fd==-1)
    {
        perror("create socket error!");
        return 0;
    }
    else
    {
        printf("Success to create socket %d\n",sock_fd);
    }

    //设置server地址结构
    bzero(&serv_addr,sizeof(serv_addr));    //初始化结构占用内存
    serv_addr.sin_family=AF_INET;    //设置传输层类型IPv4
    serv_addr.sin_port=htons(EHCO_PORT);    //设置端口号
    serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");    //设置服务器IP地址
    bzero(&(serv_addr.sin_zero),8);

    //连接服务端
    if(-1==connect(sock_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)))
    {
         perror("connect fail!");
         close(sock_fd);
         return 0;
    }
    printf("Success connect to server!\n");
    pthread_create(&thread, NULL, client_handle, NULL);
    //发送并接收缓冲的数据
    while((n=recv(sock_fd,recv_buff,1024,0))>0)
    {
        printf("%s",recv_buff);
        if(0==strncmp(recv_buff,"quit",4))
        {
            pthread_cancel(&thread);
			break;
        }
		memset(recv_buff,0,sizeof(recv_buff));
    }
    close(sock_fd);
    return 0;
}

有了这个可以在阿里云服务器搭个服务端,这样就可以用不同的客户端通过服务器通信。