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

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

相关推荐
liuqs3321 小时前
nat123安卓和nat123全端口选型指南,映射工具怎么挑
网络·笔记
x_x-F2 小时前
网络数据从网卡到用户态:一场基于内存所有权转移的接力赛
开发语言·网络·php
-今昭-2 小时前
Ansible
linux·运维·ansible
mounter6253 小时前
MACsec 全景解析:从技术演进、核心架构到 DPU 硬件卸载与 K8s 大规模调度实战
linux·kubernetes·linux kernel·kernel·macsec
IT邦德4 小时前
Dify1.6基于ubuntu系统的部署实战
linux·运维·ubuntu
非凡ghost4 小时前
分区助手:Windows 磁盘管理的“瑞士军刀“,分区调整不再怕丢数据
服务器·windows·电脑·软件需求
许彰午5 小时前
# allbytaskid——一个接口扛六个DataStore
运维·服务器·php
吠品5 小时前
Java byte数组与String互转:编码细节与踩坑记录
java·linux·服务器
木白CPP5 小时前
Linux 驱动UART子系统源码分析
linux·运维·服务器·驱动开发·嵌入式硬件·开源软件
RisunJan6 小时前
Linux命令-times(进程累计时间显示)
linux·运维·chrome