网络第4天

TCP并发服务器(多进程)

cpp 复制代码
#include <myhead.h>
#define IP "192.168.124.74"
#define PORT 6666


int fork_child(int newfd,struct sockaddr_in cin);

void re_fork(){
	while(waitpid(-1,NULL,WNOHANG)>0);
}

int main(int argc, const char *argv[])
{
	if(signal(17,re_fork)==SIG_ERR){
		ERR_MSG("signal");
		return -1;
	}

	//创建socket文件
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	printf("sfd create success\n");

	//绑定服务器的IP和端口号
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);

	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
		ERR_MSG("bind");
		return -1;
	}
	printf("bind IP&PORT success\n");

	//将文件转为被动监听模式
	if(listen(sfd,128)<0){
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success\n");

	struct sockaddr_in cin;
	socklen_t len=sizeof(cin);
	int newfd =0;
	int cpid=0;
	while(1){
		//用连接成功的客户端的信息生成accept文件

		newfd=accept(sfd,(struct sockaddr*)&cin,&len);
		if(newfd<0){
			ERR_MSG("accept");
			return -1;
		}	
		cpid=fork(); //父进程创建newfd,子进程负责通信
		if(cpid==0){
			fork_child(newfd,cin);
			exit(0);
		}else if(cpid<0){
			ERR_MSG("fork");
			return -1;
		}
		//把客户端的IP和端口提出来
		printf("newfd:%d %s:%d 连接成功\n",newfd\
				,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));

		close(newfd);//后面每个的进程文件号都是4,因为被父进程关了
	}
	//关闭所有文件描述符
	close(sfd);

	return 0;
}

int fork_child(int newfd,struct sockaddr_in cin)
{
	char buf[128]="";
	ssize_t res=0;

	while(1){
		bzero(buf,sizeof(buf));
		//接收客户端数据
		res=recv(newfd,&buf,sizeof(buf),0);
		if(res<0){
			ERR_MSG("recv");
			break;
		}else if(res==0){
			printf("客户端下线\n");
			break;
		}
		printf("[%s:%d]:%s\n",\
				inet_ntoa(cin.sin_addr),\
				ntohs(cin.sin_port),buf);

		//向客户端发送数据
		//要发送的数据
		strcat(buf,"^-^");
		res=send(newfd,buf,sizeof(buf),0);
		if(res<0){
			ERR_MSG("send");
			return -1;
		}
		printf("send success\n");
	}
	return 0;
}

TCP并发服务器(多线程)

cpp 复制代码
#include <myhead.h>
#define IP "192.168.124.74"
#define PORT 6666

struct data{
	int newfd;
	struct sockaddr_in cin;
};

void* pthread_child(void* arg);

int main(int argc, const char *argv[])
{
	
	//创建socket文件
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	printf("sfd create success\n");

	//允许端口快速被复用---监测端口号是否真的有进程在占用,如果没有,则快速复用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速复用成功\n");

	//绑定服务器的IP和端口号
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);
	
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
		ERR_MSG("bind");
		return -1;
	}
	printf("bind IP&PORT success\n");

	//将文件转为被动监听模式
	if(listen(sfd,128)<0){
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success\n");

	struct sockaddr_in cin;
	socklen_t len=sizeof(cin);
	pthread_t tid;
	struct data info;
	
	while(1){
		//用连接成功的客户端的信息生成accept文件

		info.newfd=accept(sfd,(struct sockaddr*)&info.cin,&len);
		if(info.newfd<0){
			ERR_MSG("accept");
			return -1;
		}
		
		//把客户端的IP和端口提出来
		printf("newfd:%d %s:%d 连接成功\n",info.newfd\
				,inet_ntoa(info.cin.sin_addr),ntohs(info.cin.sin_port));

		//创建线程
		if(pthread_create(&tid,NULL,pthread_child,(void*)&info)!=0){
			printf("pthread_child create fail\n");
			return -1;
		}
		//分离线程:join会阻塞,使用detach直接分离回收
		if(pthread_detach(tid)!=0){
			printf("pthread_detach fail\n");
			return -1;
		}

	}
	//关闭所有文件描述符
	close(sfd);
	return 0;
}

void* pthread_child(void* arg) //void* arg=&info
{
    //必须转存,因为info每连接一个客户端就会改变
	int newfd=((struct data*)arg)->newfd;
	struct sockaddr_in cin=((struct data*)arg)->cin;

	ssize_t res=0;
	char buf[128]="";
	while(1){
		bzero(buf,sizeof(buf));
		//接收客户端数据
		res=recv(newfd,&buf,sizeof(buf),0);
		if(res<0){
			ERR_MSG("recv");
			break;
		}else if(res==0){
			printf("客户端下线\n");
			break;
		}
		printf("[%s:%d]:%s\n",\
				inet_ntoa(cin.sin_addr),\
				ntohs(cin.sin_port),buf);

		//向客户端发送数据
		//要发送的数据
		strcat(buf,"^-^");
		res=send(newfd,buf,sizeof(buf),0);
		if(res<0){
			ERR_MSG("send");
			break;
		}
		printf("send success\n");
	}
	close(newfd);
}
相关推荐
前鼻音太阳熊15 分钟前
【MES系统】- 工业HMI状态机可视化实践:从手写SVG到Cytoscape.js的技术选型与踩坑
开发语言·javascript·ecmascript
阿米亚波31 分钟前
【C++ STL】std::array
java·开发语言·c++
白狐_79834 分钟前
【408计算机网络|第03章·上|408-CN-03A】数据链路层(上):组帧、差错控制与可靠传输
网络·网络协议·计算机网络
wuyk5551 小时前
66.嵌入式C语言进阶:共用体(Union)实战指南——单片机内存省一半的神级技巧
c语言·开发语言·stm32·单片机·嵌入式硬件
Ivanqhz1 小时前
Rust #[derive(Serialize)]浅析
开发语言·后端·rust
老赵的博客1 小时前
工控机之udp远程控制
网络·网络协议·udp
怪奇云呼军1 小时前
闪电智能 Voice Agent 怎样根据语速、停顿和追问方式切换话术?策略引擎拆解
开发语言·人工智能·网络协议·算法·语音识别·web app
努力努力再努力wz1 小时前
【分布式系统与 RPC 框架系列】从单机瓶颈到远程调用:一文理解分布式架构与 RPC 原理
linux·网络·c++·分布式·网络协议·rpc·架构
Ivanqhz1 小时前
Rust parse() 浅析
开发语言·后端·rust
神仙别闹1 小时前
基于C++实现(控制台)景区旅游管理系统
开发语言·c++·旅游