Linux——回射服务器多并发(多线程)

多线程与多进程的做法区别不大,思路一样,都是执行两个死循环,一个循环等待客户端连接,一个循环与客户端通信。多进程的方式请点此处

服务器

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

typedef struct client_new
{
    char *ip_addr;
    int sockid;
}client_new;//存放当前客户端信息

void *do_work(void *client_)
{
	client_new client=*((client_new *)client_);//强转
	char receive[100]={0};
	while(1)
	{
		memset(receive,0,sizeof(receive));
		int ret=read(client.sockid,receive,sizeof(receive));//socket作为文件描述符默认为阻塞,当客户端关闭时立即返回0
		if(ret==0)
		{
			printf("%s 客户端已关闭\n",client.ip_addr);
			pthread_exit(NULL);
		}
		printf("%s  :",client.ip_addr);
		fputs(receive,stdout);
		write(client.sockid,receive,ret);
	}
}
int main()
{
	int client_sockid=0;
	struct sockaddr_in sock;
	memset(&sock,0,sizeof(sock));
	sock.sin_family=AF_INET;
	sock.sin_port=htons(5188);
	sock.sin_addr.s_addr=htonl(INADDR_ANY);
	int sockid=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	const int on=1;
	if(setsockopt(sockid,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0)//设置端口重复利用
	{
		printf("setsockopt\n");
		return 0;
	}
	if(bind(sockid,(struct sockaddr *)&sock,sizeof(sock))<0)
	{
		printf("bind\n");
		return 0;
	}
	if(listen(sockid,SOMAXCONN)<0)
	{
		printf("listen\n");
		return 0;
	}
	struct sockaddr_in client_sockaddr;
	socklen_t other_socklen=sizeof(client_sockaddr);
	pthread_t tid=0;
	while(1)
	{
		client_sockid=accept(sockid,(struct sockaddr *)&client_sockaddr,&other_socklen);//如果没有客户端连接,accept就阻塞在这里
		if(client_sockid<0)
		{
			continue;
		}
		client_new client;
		client.ip_addr=inet_ntoa(client_sockaddr.sin_addr);
		client.sockid=client_sockid;
		printf("ip=%s  port=%d   已连接\n",inet_ntoa(client_sockaddr.sin_addr),ntohs(client_sockaddr.sin_port));
		pthread_create(&tid,NULL,do_work,(void *)&client);//创建线程,只要有客户端连接就创建一个线程去和客户端通信
	}
	close(sockid);
	return 0;
}

客户端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>


int main()
{
	struct sockaddr_in sock;
	memset(&sock,0,sizeof(sock));
	sock.sin_family=AF_INET;
	sock.sin_port=htons(5188);
	sock.sin_addr.s_addr=inet_addr("127.0.0.1");

	int sockid=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	socklen_t socklen=sizeof(sock);
	if(connect(sockid,(struct sockaddr *)&sock,socklen)<0)
	{
		printf("connect\n");
		return 0;
	}

	char send[100]={0};
	char receive[100]={0};
	while(1) 
	{
		fgets(send,sizeof(send),stdin);
		if(strcmp(send,"NULL\n")==0)//输入NULL退出客户端
		{
			break;
		}
		write(sockid,send,strlen(send));
		read(sockid,receive,sizeof(receive));
		fputs(receive,stdout);
		memset(receive,0,strlen(receive));
		memset(send,0,strlen(send));
	}
	close(sockid);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值