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

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

相关推荐
星辰云-10 分钟前
# Linux Centos系统硬盘分区扩容
linux·运维·centos·磁盘扩容
聽雨23730 分钟前
02每日简报20250704
linux·科技·金融·生活·社交电子·娱乐·媒体
Maki Winster1 小时前
Peek-Ubuntu上Gif录制工具-24.04LTS可装
linux·ubuntu·peek
qq_171538851 小时前
TCP/IP协议精解:IP协议——互联网世界的邮政编码系统
网络·网络协议·tcp/ip
珹洺1 小时前
计算机网络:(七)网络层(上)网络层中重要的概念与网际协议 IP
网络·tcp/ip·计算机网络
小皮侠2 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
兮动人2 小时前
获取终端外网IP地址
java·网络·网络协议·tcp/ip·获取终端外网ip地址
Maki Winster2 小时前
在 Ubuntu 下配置 oh-my-posh —— 普通用户 + root 各自使用独立主题(共享可执行)
linux·运维·ubuntu
怦然星动_2 小时前
eNSP中实现vlan间路由通信(路由器)
网络·智能路由器
守望时空332 小时前
Linux下KDE桌面创建自定义右键菜单
linux