网络第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);
}
相关推荐
JaguarJack19 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo19 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理2 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
DianSan_ERP2 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
feifeigo1232 天前
matlab画图工具
开发语言·matlab
dustcell.2 天前
haproxy七层代理
java·开发语言·前端
norlan_jame2 天前
C-PHY与D-PHY差异
c语言·开发语言
多恩Stone2 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
呉師傅2 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑