epoll的并发服务器(TCP服务器与客户端通信)

服务器:

复制代码
#include<myhead.h>
#define IP "192.168.250.100"
#define PORT 8888
/*
typedef union epoll_data {
	void        *ptr;
	int          fd;
	uint32_t     u32;
	uint64_t     u64;
} epoll_data_t;

struct epoll_event {
	uint32_t     events;      	
	epoll_data_t data;        
};
*/

int main(int argc, const char *argv[])
{
	//创建流式套接字
	int sfd = socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
	}
	printf("socket success\n");
	//允许端口快速被重用
	int reuse=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
	{
		ERR_MSG("setsockopt");
	}
	printf("setsockopt 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");
	}
	printf("bind success\n");

	//设置套接字为被动监听状态
	if(listen(sfd,128)<0)
	{
		ERR_MSG("listen");
	}
	printf("listen success\n");

	//存储客户端地址信息
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);

	//定义事件结构体
	struct epoll_event event;
	//定义存放就绪事件描述符的数组
	struct epoll_event events[10];

	//创建红黑树根节点
	int epfd = epoll_create(1);
	if(epfd<0)
	{
		ERR_MSG("epoll_create");
	}
	printf("成功创建红黑树根节点\n");

	//添加要检测的事件描述符
	event.events=EPOLLIN;
	event.data.fd=sfd;
	if(epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&event)<0)
	{
		ERR_MSG("epoll_ctl");
	}
	printf("成功将sfd事件描述符挂载到红黑树上\n");


	char buf[256]="";
	int newfd=-1;
	while(1)
	{
		int ret=epoll_wait(epfd,events,10,-1);
		for(int i=0;i<ret;i++)
		{
			if(events[i].data.fd == sfd)
			{
				//获取连接成功后的新套接字
				newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
				if(newfd<0)
				{
					ERR_MSG("accept");
				}
				printf("[%s : %d] newfd=%d 客户端连接成功\n", \
						inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd);

				//添加要检测的事件描述符
				event.events=EPOLLIN;
				event.data.fd=newfd;
				if(epoll_ctl(epfd,EPOLL_CTL_ADD,newfd,&event)<0)
				{
					ERR_MSG("epoll_ctl");
				}
				printf("成功将newfd:%d事件描述符挂载到红黑树上\n",newfd);
			}
			else
			{
				int cfd=events[i].data.fd;
				int len=read(cfd,buf,sizeof(buf));
				if(len<=0)
				{
					close(cfd);
					epoll_ctl(epfd,EPOLL_CTL_DEL,cfd,NULL);
				}
				else
				{
					buf[len]='\0';
					printf("接收的数据:%s\n",buf);
					strcat(buf,"*-*");
					write(cfd,buf,sizeof(buf));
				}
			}

		}
	}

	close(newfd);

	//关闭文件描述符
	if(close(sfd) < 0)
	{
		ERR_MSG("close");
		return -1;
	}
	return 0;
}	

客户端:

复制代码
#include<myhead.h>
#define IP "192.168.250.100"
#define PORT 8888
int main(int argc, const char *argv[])
{
	//创建流式套接字
	int cfd=socket(AF_INET,SOCK_STREAM,0);
	if(cfd<0)
	{
		ERR_MSG("socket");
	}
	printf("socket success\n");

	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);

	//连接服务器
	if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("connect");
	}
	printf("connect success\n");

	char buf[256]="";
	while(1)
	{
		memset(buf,0,sizeof(buf));
		printf("请输入发送的信息:");
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1]='\0';
		write(cfd,buf,sizeof(buf));

		int len = read(cfd, buf, sizeof(buf));
        if (len <= 0) 
		{
			ERR_MSG("read");
        } 
		printf("接收服务器返回的信息:%s\n",buf);
	}
	return 0;
}	

测试现象:

相关推荐
不做菜鸟的网工21 小时前
BGP特性
网络协议
MrSYJ1 天前
TCP协议理解
后端·tcp/ip
明月_清风3 天前
开发者网络概念全扫盲:一篇搞定
后端·网络协议
刘马想放假3 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
王二端茶倒水4 天前
一套可落地的无线运营方案,不能只管 AP,还要管用户、计费和运维
网络协议
162723816084 天前
EtherCAT 分布式时钟(DC)原理与配置实战:把多轴真正"对齐到同一时刻"
网络协议
王二端茶倒水5 天前
宽带无线项目,怎么从一次性交付变成长期运营收入?
网络协议
用户2530171996276 天前
第6篇:从技术到产品 — Ghost Proxifier 的设计哲学
网络协议
用户2530171996276 天前
第3篇:注入的艺术 — Ghost Proxifier 核心架构拆解
网络协议