双11服务器

复制代码
#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/un.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include <netinet/in.h>
 #include <arpa/inet.h>
#include <pthread.h>
#include<unistd.h>

//看服务器性能,看服务器,进行限流
//后面用线程池来优化
void *run(void *arg)
{
    int cli_fd=*(int*)arg;
	char buf[4096]={};
	size_t buf_size=sizeof(buf);
    
	while(1)
	{
		//接收客户端数据
		//int ret=read(cli_fd,buf,buf_size);
		int ret=recv(cli_fd,buf,buf_size,0);	
		if(ret<=0||0==strcmp(buf,"quit"))
		{
			printf("%d客户端请求退出\n",cli_fd);
			break;
		}
		printf("from %d revc:%s  bits:%d\n",cli_fd,buf,ret);
		//发送数据给客户端
		//把传过来的数据拼接:return后给客户端
		strcat(buf,"return");
		ret=send(cli_fd,buf,strlen(buf)+1,0);
		if(ret<=0)
		{
			printf("客户端%d退出\n",cli_fd);
			break;
	}
}
	//关闭
	close(cli_fd);	
	exit(0);
}

int main(int argc,const char* argv[])
{
	//创建socket
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		perror("socket error");
		exit(1);
	}
	//准备自己的地址通讯地址
	struct 	 sockaddr_in  addr={};
	addr.sin_family=AF_INET;
	addr.sin_port=htons(8888);
	addr.sin_addr.s_addr=inet_addr("127.0.0.1");
	socklen_t addrlen=sizeof(addr);

	//绑定
	if(bind(sockfd,(struct sockaddr*)&addr,addrlen)<0)
	{
		perror("bind error");
		return -1;
	}
	//监听
	if(listen(sockfd,5)<0)
	{
		perror("listen error");
		return -1;
	}
pthread_t tid;
	for(;;)
	{
		//等待客户端连接

		struct sockaddr_in src_addr={};
        //连接,src_addr来接受客户端的ip来进行通讯存到clifd
        //客户端的映射clifd
        
        
 //小芳讨论:结果是因为这个for太快了,导致本轮clifd还没来的及销毁,下个clifd用的还是之前的那个clifd;!!!
 //解决方法一加一个usleep(1);下面已经写了 ,    解决方法二看下一篇代码详解!!!!!
		int clifd=accept(sockfd,(struct sockaddr*)&src_addr,&addrlen);
		if(clifd<0)
		{
			perror("accept error");
			continue;
		}	
        
        
        
		//创建线程处理客户端请求
        pthread_create(&tid,NULL,run,&clifd);//因为每次都是重新执行for循环,所以一直为3
       //clifd共用的是同一片空间的clifd
		//等待一个线程结束
		usleep(1);
	
		
	}
    return 0;
}

2.可能会覆盖,采用下面的方案进行改进

复制代码
#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/un.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include <netinet/in.h>
 #include <arpa/inet.h>
#include <pthread.h>
#include<unistd.h>
//进程是线程的池子
//当前线程数量
size_t client_count=0;
//线程多了同时返回可能会有问题
typedef struct Client{
    int cli_fd;
	pthread_t tid;
	struct sockaddr_in cli_addr;
}Client;
typedef struct sokcaddr *sp;

//看服务器性能,看服务器,进行限流
//后面用线程池来优化
void *run(void *arg)
{
	//立刻保存,否则新的连接会覆盖上一次连接,导致操作的都可能都是最后一个线程
   // int cli_fd=*(int*)arg;//?
	//不需要保存,因为cient专门会为此客户端访问,不会修改
	Client *client=(Client*)arg;


	char buf[4096]={};
	size_t buf_size=sizeof(buf);
    
	while(1)
	{
		//接收客户端数据
		//int ret=read(cli_fd,buf,buf_size);
		int ret=recv(client->cli_fd,buf,buf_size,0);	
		if(ret<=0||0==strcmp(buf,"quit"))
		{
			printf("%d客户端请求退出\n",client->cli_fd);
			close(client->cli_fd);
			client->cli_fd=0;//表示断开
			client_count--;
			return NULL;
		}
		printf("from %d revc:%s  bits:%d\n",client->cli_fd,buf,ret);
		//发送数据给客户端
		//把传过来的数据拼接:return后给客户端
		strcat(buf,"return");
		ret=send(client->cli_fd,buf,strlen(buf)+1,0);
		if(ret<=0)
		{
			close(client->cli_fd);
			client->cli_fd=0;
			client_count--;
		
			printf("客户端%d退出\n",client->cli_fd);			
			return NULL;
		}
	}

	//关闭
	close(client->cli_fd);	
	exit(0);
}

int main(int argc,const char* argv[])
{
	//创建socket
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		perror("socket error");
		exit(1);
	}
	//准备自己的地址通讯地址
	struct 	 sockaddr_in  addr={};
	addr.sin_family=AF_INET;
	addr.sin_port=htons(8888);
	addr.sin_addr.s_addr=inet_addr("127.0.0.1");
	socklen_t addrlen=sizeof(addr);

	//绑定
	if(bind(sockfd,(struct sockaddr*)&addr,addrlen)<0)
	{
		perror("bind error");
		return -1;
	}
	//监听
	if(listen(sockfd,5)<0)
	{
		perror("listen error");
		return -1;
	}
Client*client=(Client*)calloc(50,sizeof(Client));
size_t index=0;
	for(;;)
	{
		//找空闲的client(cli_fd为0,认为是空闲的)
		while(client[index].cli_fd)
		{
			//若没有空闲的则等10s在继续尝试
			if(client_count>=50)
			{
				usleep(100000);
			}
			
			index=(index+1)%50;//0-49循环
		}
		//从上面的循环出来,则第index个client一定空闲
        //使用molloc会开辟新的套接字
        
 //小芳讨论:上一篇提到的问题,因为上面while(client[index].cli_fd),每一个client[index]都不一样
		client[index].cli_fd=accept(sockfd,(struct sockaddr*)&client[index].cli_addr,&addrlen);
		if(client[index].cli_fd<0)
		{
			perror("accept error");
			continue;
		}
        //创建的时候后移用不同的变量来存储
			pthread_create(&client[index].tid,NULL,run,&client[index]);
       //每次传的clifd都不一样,一个萝卜一个坑
		client_count++;
        //COLOR_BGR2GRAY
	}
    return 0;
}

区别参考如下:致小方的一封信

相关推荐
雯宝2 小时前
mnt_init 函数
linux
律宏阔8 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔8 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴8 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千8 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei378 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei378 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei378 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW8 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
百万蹄蹄向前冲8 小时前
双端同步!云服务器装最新Node.js v26.10全过程追踪
服务器·人工智能·node.js