网络第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);
}
相关推荐
笃励14 分钟前
Java面试题二
java·开发语言·python
jyan_敬言23 分钟前
【Linux】Linux命令与操作详解(一)文件管理(文件命令)、用户与用户组管理(创建、删除用户/组)
linux·运维·服务器·c语言·开发语言·汇编·c++
FL162386312927 分钟前
[C#]C# winform部署yolov11-pose姿态估计onnx模型
开发语言·yolo·c#
笑非不退38 分钟前
C++ 异步编程 并发编程技术
开发语言·c++
车载诊断技术1 小时前
什么是汽车中的SDK?
网络·架构·汽车·soa·电子电器架构
一颗星星辰1 小时前
Python | 第九章 | 排序和查找
服务器·网络·python
爱写代码的刚子1 小时前
C++知识总结
java·开发语言·c++
martian6651 小时前
QT开发:基于Qt实现的交通信号灯模拟器:实现一个带有倒计时功能的图形界面应用
开发语言·qt
冷琴19961 小时前
基于java+springboot的酒店预定网站、酒店客房管理系统
java·开发语言·spring boot
ZachOn1y1 小时前
计算机网络:计算机网络概述:网络、互联网与因特网的区别
网络·计算机网络·知识点汇总·考研必备