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

7 篇文章 3 订阅
5 篇文章 0 订阅

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;
}

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

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于 Python 的 Socket 实现的 UDP 多线程通信客户端和服务端的示例代码: 服务端代码: ``` import socket import threading # 定义服务器地址和端口号 HOST = '127.0.0.1' PORT = 8000 # 创建 UDP Socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_socket.bind((HOST, PORT)) def receive_thread(): while True: data, client_address = server_socket.recvfrom(1024) print(f'Received message from {client_address}: {data.decode()}') def send_thread(): while True: message = input("please input message: ") server_socket.sendto(message.encode(), (HOST, PORT)) # 创建接收和发送线程 receive_t = threading.Thread(target=receive_thread) send_t = threading.Thread(target=send_thread) # 启动线程 receive_t.start() send_t.start() # 等待线程结束 receive_t.join() send_t.join() # 关闭 Socket server_socket.close() ``` 客户端代码: ``` import socket import threading # 定义服务器地址和端口号 HOST = '127.0.0.1' PORT = 8000 # 创建 UDP Socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) def receive_thread(): while True: data, server_address = client_socket.recvfrom(1024) print(f'Received message from {server_address}: {data.decode()}') def send_thread(): while True: message = input("please input message: ") client_socket.sendto(message.encode(), (HOST, PORT)) # 创建接收和发送线程 receive_t = threading.Thread(target=receive_thread) send_t = threading.Thread(target=send_thread) # 启动线程 receive_t.start() send_t.start() # 等待线程结束 receive_t.join() send_t.join() # 关闭 Socket client_socket.close() ``` 在上面的代码中,服务端和客户端的实现基本相同,只是在绑定 Socket 和发送消息时的地址和端口号不同。服务端使用了 server_socket.bind() 方法来将 Socket 绑定到指定的地址和端口号上,并使用 server_socket.recvfrom() 方法来接收客户端发送的消息。客户端使用了 client_socket.sendto() 方法来将消息发送给服务端,并使用 client_socket.recvfrom() 方法来接收服务端返回的响应。 需要注意的是,由于 UDP 是无连接的协议,因此每次发送消息时都需要指定目标地址和端口号。在本示例中,我们将其设置为 HOST 和 PORT。另外,由于是多线程通信,因此需要注意线程安全问题。可以使用锁等机制来保证数据的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值