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

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

相关推荐
科技象限3 分钟前
数据防泄漏系统:文件是怎么溜出门的,就该怎么堵
运维·网络·网络安全·安企神
听说66623 分钟前
信息安全工程师 - 第二十二章 网站安全需求分析与安全保护工程
网络·安全·web安全·网络安全·系统安全
云和数据.ChenGuang1 小时前
name=“张三“ age=18 weight=100.3 print (name,age,weight)
java·服务器·前端
学IT的周星星1 小时前
记忆系统:让 Agent 记住你是谁、上次聊到哪
运维·服务器·人工智能·windows·大模型·llm·agent
en.en..1 小时前
MRS/MSR 指令操作 xPSR 寄存器
linux·运维·服务器
Brilliantwxx2 小时前
【Linux】 自主shell编写巩固复习篇
linux·运维·服务器·开发语言
弯_弯2 小时前
FDE 的工程能力画像:数据接入、PoC 与可复用资产的落地口径
java·服务器·开发语言
鱼很腾apoc2 小时前
【MySQL】第3期 索引、事务与视图系统详解
linux·mysql·事务·索引·dml·视图·macc
anew___2 小时前
《从零手写操作系统 (49):虚拟内存进阶——Demand Paging、Swap与缺页异常处理》
linux·服务器·php
迷途之人不知返2 小时前
【基础IO】-4-再谈重定向
linux