网络第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);
}
相关推荐
JSON_L几秒前
PHP 高精度计算完全指南:彻底解决浮点数精度丢失
开发语言·php
treesforest5 分钟前
如何查IP归属地?IP地址归属地查询的三种方式与选型指南
网络·数据库·网络协议·tcp/ip
江屿风6 分钟前
C++OJ题经验总结(竞赛)3
开发语言·c++·笔记·算法
guygg8813 分钟前
用 MATLAB 实现步进电机控制的仿真方案
开发语言·matlab
码农的小菜园13 分钟前
Java创建单例
java·开发语言·单例模式
yuan1999715 分钟前
基于物理光学(波动光学)模型的 MATLAB 程序
开发语言·matlab
香蕉鼠片17 分钟前
八股C++(二)
开发语言·c++
影寂ldy17 分钟前
C#数组的高级方法
开发语言·c#
zzzsde18 分钟前
【Linux网络】传输层协议UDP
linux·服务器·开发语言·网络·算法·udp
星恒讯工业路由器18 分钟前
WiFi 安全技术演进全解析:从 WEP 到 WPA3 的迭代与安全蜕变
网络·安全·wifi·信息与通信