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

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

相关推荐
Empty-Filled20 分钟前
AI生成测试用例功能怎么测:一个完整实战案例
网络·人工智能·测试用例
峥无1 小时前
Linux系统编程基石:静态库·动态库·ELF文件·进程地址空间全景图
linux·运维·服务器
用户2367829801681 小时前
从 chmod 755 说起:Unix 文件权限到底是怎么算的?
linux
码云数智-大飞1 小时前
本地部署大模型:隐私安全与多元优势一站式解读
运维·网络·人工智能
Strugglingler1 小时前
【systemctl 学习总结】
linux·systemd·systemctl·journalctl·unit file
jinanwuhuaguo1 小时前
(第二十九篇)OpenClaw 实时与具身的跃迁——从异步孤岛到数字世界的“原住民”
前端·网络·人工智能·重构·openclaw
等风来不如迎风去2 小时前
【win11】最佳性能:fix 没有壁纸,一直黑屏
网络·人工智能
Harvy_没救了2 小时前
【网络部署】 Win11 + VMware CentOS8 + Nginx 文件共享服务 Wiki
运维·网络·nginx
嵌入式×边缘AI:打怪升级日志3 小时前
100ASK-T113 Pro 开发板 Bootloader 完全开发指南
linux·ubuntu·bootloader
lzhdim3 小时前
SQL 入门 12:SQL 视图:创建、修改与可更新视图
java·大数据·服务器·数据库·sql