linux网络编程----->高并发--->poll多路I/O转接服务器

做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.

常见的linux并发服务器模型;

  • 多进程并发服务器
  • 多线程并发服务器
  • select多路I/O转接服务器
  • poll多路I/O转接服务器
  • epool多路I/O转接服务器.

本次主要讨论poll多路I/转接并发服务器模型:

前几章介绍完了多进程并发服务器,  多线程并发服务器, selete多路I/O转接服务器,  本章开始介绍poll(linux特有)多路I/O转接模型.

由于多进程和多线程模型在实现中相对简单, 但由于其开销和CPU高度中比较大, 所以一般不用多线程和多进程来实现服务模型. select由于其跨平台, 但其最高上限默认为1024, 修改突破1024的话需要重新编译linux内核, poll完美解决了1024的限制.

主要用到API:

poll(struct pollfd *fds, nfds_t nfds, int timeout);

fds:  传入传出结构体数组

nfds: 结构体数组数量

timeout: 监听时间

-1 阻塞等待

0 立刻返回, 不阻塞

>0 等待毫秒数

struct pollfd{

int fd;              //监听的文件描述符

int events;      //监听的事件 POLLIN监听读 POLLOUT 监听写 POLLERR 监听异常

int revents;    // 监听事件中满足条件返回的事件

.server[以下代码都没有做错误判断,  加上错误判断会造成代码翻倍, 实际开发中需要特别注意返回值]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>

#define CLIENT_MAX 1024		//定义最大客户端监听
#define SERV_PORT 9096		//监听端口

int main(int argc, char* argv[]){
	int listenfd, connfd;
	struct sockaddr_in serv_addr, clie_addr;
	socklen_t clie_addr_len;
	struct pollfd event[CLIENT_MAX];
	int maxi, opt, i, j, nready, n;
	char buf[BUFSIZ];

	//创建tcp监听套接字
	listenfd = socket(AF_INET, SOCK_STREAM, 0);

	//设置端口复用
	opt = 1;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	//初始化为0
	bzero(&serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	//设置端口并转换为网络字节序
	serv_addr.sin_port = htons(SERV_PORT);
	//设置本机任意ip
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//绑定listenfd
	bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

	//设置同时连接上限
	listen(listenfd, SOMAXCONN);	//#define SOMAXCONN 128

	//将监听套接字连接至事件
	event[0].fd = listenfd;
	event[0].events = POLLIN;

	//初始化
	for(i = 1; i < CLIENT_MAX; i++){
		event[i].fd = -1;
	}

	maxi = 0;
	for(;;){
		nready = poll(event, maxi+1, -1);

		//客户端请求连接
		if(event[0].revents & POLLIN){
			clie_addr_len = sizeof(clie_addr);
			//获取连接
			connfd = accept(listenfd, (struct sockaddr*)&clie_addr, &clie_addr_len);
			//打印提示
			printf("%s:%d client connect successfully!\n", inet_ntoa(clie_addr.sin_addr), ntohs(clie_addr.sin_port));

			//添加至监听
			for(i = 1; i < CLIENT_MAX; i++){
				if(0 > event[i].fd){
					event[i].fd = connfd;
					break;
				}
			}
			//判断监听是否已满
			if(CLIENT_MAX == i){
				//关闭连接
				printf("too many clients!\n");
				close(connfd);
				continue;
			}
			//监听读事件
			event[i].events = POLLIN;
			if(i > maxi)
				maxi = i;

			if(0 == (--nready))
				continue;
		}

		for(i = 1; i <= maxi; i++){
			if(0 > event[i].fd)
				continue;

			//是否有事件
			if(event[i].revents & POLLIN){
				//清空
				bzero(buf, sizeof(buf));
				n = read(event[i].fd, buf, sizeof(buf));
				//对方是否已关闭
				if(0 == n){
					clie_addr_len = sizeof(clie_addr);
					//获取客户端信息
					getpeername(event[i].fd, (struct sockaddr*)&clie_addr, &clie_addr_len);
					printf("%s:%d client disconnect successfully!\n", inet_ntoa(clie_addr.sin_addr), ntohs(clie_addr.sin_port));
					//关闭客户端连接
					close(event[i].fd);
					//将事件数组中初始化为-1
					event[i].fd = -1;
				}else if(0 < n){
					//转换为大写
					for(j = 0; j < n; j++){
						buf[j] = toupper(buf[j]);
					}
					//回写给客户端
					write(event[i].fd, buf, n);
				}
				if(0 == (--nready)){
					break;
				}
			}
		}
	}
	close(listenfd);
	return 0;
}
时间: 2024-10-13 11:45:17

linux网络编程----->高并发--->poll多路I/O转接服务器的相关文章

linux网络编程-----&gt;高并发---&gt;epoll多路I/O转接服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论poll多路I/转接并发服务器模型: 前几章介绍完了多进程并发服务器,  多线程并发服务器, selete多路I/O转接服务器,  poll多路I/O转接服务器, 本章开始介

linux网络编程-----&gt;高并发---&gt;select多路I/O复用服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论select多路I/O转接服务器模型: 使用select多路I/O转接服务器模型要考虑到以下几点: 1. select能监听的文件描述符个数受限于FD_SETSIZE, 一般

linux网络编程-----&gt;高并发---&gt;多进程并发服务器

在做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论多线程并发服务器模型: 使用多进程并发服务器时要考虑以下几点: 父进程最大文件描述个数(父进程中需要close关闭accpet返回的新文件描述符) 系统内创建进程个数(与内

linux网络编程-----&gt;高并发---&gt;多线程并发服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论多线程并发服务器模型: 使用多线程模型开发服务时需要考虑以下问题 1.  调整进程内最大文件描述符上限. 2.  线程如有共享数据, 考虑线程同步. 3.  服务于客户端线程

Linux网络编程——tcp并发服务器(poll实现)

想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/O复用之poll函数> 代码: #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h> #include <sys/socket.h> #incl

Linux网络编程——tcp并发服务器(多进程)

一.tcp并发服务器概述 一个好的服务器,一般都是并发服务器(同一时刻可以响应多个客户端的请求).并发服务器设计技术一般有:多进程服务器.多线程服务器.I/O复用服务器等. 二.多进程并发服务器 在 Linux 环境下多进程的应用很多,其中最主要的就是网络/客户服务器.多进程服务器是当客户有请求时,服务器用一个子进程来处理客户请求.父进程继续等待其它客户的请求.这种方法的优点是当客户有请求时,服务器能及时处理客户,特别是在客户服务器交互系统中.对于一个 TCP 服务器,客户与服务器的连接可能并不

linux网络编程-----实现并发访问网站------

一般在测试多并发服务器的时候需要使用多路进程访问,这时需要自己来编写测试的并发访问功能. 直接上代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> //回收子进程 void wait_child(int num){ while(0 < waitpid(0, NULL, WNOHANG)

Linux网络编程——tcp并发服务器(多线程)

tcp多线程并发服务器 多线程服务器是对多进程服务器的改进,由于多进程服务器在创建进程时要消耗较大的系统资源,所以用线程来取代进程,这样服务处理程序可以较快的创建.据统计,创建线程与创建进程要快 10100 倍,所以又把线程称为"轻量级"进程.线程与进程不同的是:一个进程内的所有线程共享相同的全局内存.全局变量等信息,这种机制又带来了同步问题. tcp多线程并发服务器框架: 我们在使用多线程并发服务器时,直接使用以上框架,我们仅仅修改client_fun()里面的内容. 代码示例: #

Linux 网络编程系列教程

01.Linux网络编程1--网络协议入门 02.Linux网络编程2--无连接和面向连接协议的区别 03.Linux网络编程3--编程准备:字节序.地址转换 04.Linux网络编程4--UDP编程 05.Linux网络编程5--广播 06.Linux网络编程7--多播 08.Linux网络编程8--TCP编程 09.Linux网络编程9--并发服务器 10.Linux网络编程10--原始套接字能干什么? 11.Linux网络编程11--原始套接字编程 12.Linux网络编程12--原始套接