基于epoll的TCP服务器端(C++)

网络编程------C++实现socket通信(TCP)高并发之epoll模式_tcp通信c++ 多客户端epoll_n大橘为重n的博客-CSDN博客

网络编程------C++实现socket通信(TCP)高并发之select模式_n大橘为重n的博客-CSDN博客

server.cpp

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <ctype.h>
#include <sys/epoll.h>	//epoll头文件

#define MAXSIZE 1024
#define IP_ADDR "127.0.0.1"
#define IP_PORT 8888

int main()
{
	int i_listenfd, i_connfd;
	struct sockaddr_in st_sersock;
	char msg[MAXSIZE];
	int nrecvSize = 0;

	struct epoll_event ev, events[MAXSIZE];
	int epfd, nCounts;	//epfd:epoll实例句柄, nCounts:epoll_wait返回值

	if((i_listenfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0)	//建立socket套接字
	{
		printf("socket Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(0);
	}

	memset(&st_sersock, 0, sizeof(st_sersock));
	st_sersock.sin_family = AF_INET;  //IPv4协议
	st_sersock.sin_addr.s_addr = htonl(INADDR_ANY);	//INADDR_ANY转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。
	st_sersock.sin_port = htons(IP_PORT);

	if(bind(i_listenfd,(struct sockaddr*)&st_sersock, sizeof(st_sersock)) < 0) //将套接字绑定IP和端口用于监听
	{
		printf("bind Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(0);
	}

	if(listen(i_listenfd, 20) < 0)	//设定可同时排队的客户端最大连接个数
	{
		printf("listen Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(0);
	}

	if((epfd = epoll_create(MAXSIZE)) < 0)	//创建epoll实例
	{
		printf("epoll_create Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(-1);
	}
	
	ev.events = EPOLLIN;
	ev.data.fd = i_listenfd;
	if(epoll_ctl(epfd, EPOLL_CTL_ADD, i_listenfd, &ev) < 0)
	{
		printf("epoll_ctl Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(-1);
	}
	printf("======waiting for client's request======\n");
	//准备接受客户端连接
	while(1)
	{
		if((nCounts = epoll_wait(epfd, events, MAXSIZE, -1)) < 0)
		{
			printf("epoll_ctl Error: %s (errno: %d)\n", strerror(errno), errno);
			exit(-1);
		}
		else if(nCounts == 0)
		{
			printf("time out, No data!\n");
		}
		else
		{
			for(int i = 0; i < nCounts; i++)
			{
				int tmp_epoll_recv_fd = events[i].data.fd;
				if(tmp_epoll_recv_fd == i_listenfd)	//有客户端连接请求
				{
					if((i_connfd = accept(i_listenfd, (struct sockaddr*)NULL, NULL)) < 0)	//阻塞等待客户端连接
					{
						printf("accept Error: %s (errno: %d)\n", strerror(errno), errno);
					//	continue;
					}	
					else
					{
						printf("Client[%d], welcome!\n", i_connfd);
					}
	
					ev.events = EPOLLIN;
					ev.data.fd = i_connfd;
					if(epoll_ctl(epfd, EPOLL_CTL_ADD, i_connfd, &ev) < 0)
					{
						printf("epoll_ctl Error: %s (errno: %d)\n", strerror(errno), errno);
						exit(-1);
					}
				}
				else	//若是已连接的客户端发来数据请求
				{
					//接受客户端发来的消息并作处理(小写转大写)后回写给客户端
					memset(msg, 0 ,sizeof(msg));
					if((nrecvSize = read(tmp_epoll_recv_fd, msg, MAXSIZE)) < 0)
					{
						printf("read Error: %s (errno: %d)\n", strerror(errno), errno);
						continue;
					}
					else if( nrecvSize == 0)	//read返回0代表对方已close断开连接。
					{
						printf("client has disconnected!\n");
						epoll_ctl(epfd, EPOLL_CTL_DEL, tmp_epoll_recv_fd, NULL);
						close(tmp_epoll_recv_fd);  //
					
						continue;
					}
					else
					{
						printf("recvMsg:%s", msg);
						for(int i=0; msg[i] != '\0'; i++)
						{
							msg[i] = toupper(msg[i]);
						}
						if(write(tmp_epoll_recv_fd, msg, strlen(msg)+1) < 0)
						{
							printf("write Error: %s (errno: %d)\n", strerror(errno), errno);
						}

					}
				}
			}
		}
	}//while
	close(i_listenfd);
	close(epfd);
	return 0;
}

client.cpp

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>
#include <arpa/inet.h>

#define MAXSIZE 1024
#define IP_ADDR "127.0.0.1"
#define IP_PORT 8888

int i_sockfd = -1;

void SigCatch(int sigNum)	//信号捕捉函数(捕获Ctrl+C)
{
	if(i_sockfd != -1)
	{
		close(i_sockfd);
	}
	printf("Bye~! Will Exit...\n");
	exit(0);
}

int main()
{
	struct sockaddr_in st_clnsock;
	char msg[1024];
	int nrecvSize = 0;

	signal(SIGINT, SigCatch);	//注册信号捕获函数

	if((i_sockfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0)	//建立套接字
	{
		printf("socket Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(0);
	}

	memset(&st_clnsock, 0, sizeof(st_clnsock));
	st_clnsock.sin_family = AF_INET;  //IPv4协议
	//IP地址转换(直接可以从物理字节序的点分十进制 转换成网络字节序)
	if(inet_pton(AF_INET, IP_ADDR, &st_clnsock.sin_addr) <= 0)
	{
		printf("inet_pton Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(0);
	}
	st_clnsock.sin_port = htons(IP_PORT);	//端口转换(物理字节序到网络字节序)

	if(connect(i_sockfd, (struct sockaddr*)&st_clnsock, sizeof(st_clnsock)) < 0)	//主动向设置的IP和端口号的服务端发出连接
	{
		printf("connect Error: %s (errno: %d)\n", strerror(errno), errno);
		exit(0);
	}

	printf("======connect to server, sent data======\n");

	while(1)	//循环输入,向服务端发送数据并接受服务端返回的数据
	{
		fgets(msg, MAXSIZE, stdin);
		printf("will send: %s", msg);
		if(write(i_sockfd, msg, MAXSIZE) < 0)	//发送数据
		{
			printf("write Error: %s (errno: %d)\n", strerror(errno), errno);
			exit(0);
		}

		memset(msg, 0, sizeof(msg));
		if((nrecvSize = read(i_sockfd, msg, MAXSIZE)) < 0)	//接受数据
		{
			printf("read Error: %s (errno: %d)\n", strerror(errno), errno);
		}
		else if(nrecvSize == 0)
		{
			printf("Service Close!\n");
		}
		else
		{
			printf("Server return: %s\n", msg);
		}

	}
	return 0;
}
相关推荐
会员源码网23 分钟前
理财源码开发:单语言深耕还是多语言融合?看完这篇不踩坑
网络·个人开发
米羊1211 小时前
已有安全措施确认(上)
大数据·网络
Fcy6481 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满1 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
主机哥哥2 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
ManThink Technology2 小时前
如何使用EBHelper 简化EdgeBus的代码编写?
java·前端·网络
珠海西格电力科技3 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
QT.qtqtqtqtqt3 小时前
未授权访问漏洞
网络·安全·web安全
释怀不想释怀3 小时前
Linux环境变量
linux·运维·服务器
zzzsde3 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器