热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux下epoll网络编程模型,LinuxIO多路复用之epoll网络编程

前言本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下:客户端从标准输

前言

本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下:

客户端从标准输入读入一行,发送到服务端

服务端从网络读取一行,然后输出到客户端

客户端收到服务端的响应,输出这一行到标准输出

服务端

代码如下:

#include

#include /* basic system data types */

#include /* basic socket definitions */

#include /* sockaddr_in{} and other Internet defns */

#include /* inet(3) functions */

#include /* epoll function */

#include /* nonblocking */

#include /*setrlimit */

#include

#include

#include

#include

#define MAXEPOLLSIZE 10000

#define MAXLINE 10240

int handle(int connfd);

int setnonblocking(int sockfd)

{

if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {

return -1;

}

return 0;

}

int main(int argc, char **argv)

{

int servPort = 6888;

int listenq = 1024;

int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;

struct sockaddr_in servaddr, cliaddr;

socklen_t socklen = sizeof(struct sockaddr_in);

struct epoll_event ev;

struct epoll_event events[MAXEPOLLSIZE];

struct rlimit rt;

char buf[MAXLINE];

/* 设置每个进程允许打开的最大文件数 */

rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;

if (setrlimit(RLIMIT_NOFILE, &rt) == -1)

{

perror("setrlimit error");

return -1;

}

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl (INADDR_ANY);

servaddr.sin_port = htons (servPort);

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if (listenfd == -1) {

perror("can't create socket file");

return -1;

}

int opt = 1;

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

if (setnonblocking(listenfd) <0) {

perror("setnonblock error");

}

if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) &#61;&#61; -1)

{

perror("bind error");

return -1;

}

if (listen(listenfd, listenq) &#61;&#61; -1)

{

perror("listen error");

return -1;

}

/* 创建 epoll 句柄&#xff0c;把监听 socket 加入到 epoll 集合里 */

kdpfd &#61; epoll_create(MAXEPOLLSIZE);

ev.events &#61; EPOLLIN | EPOLLET;

ev.data.fd &#61; listenfd;

if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) <0)

{

fprintf(stderr, "epoll set insertion error: fd&#61;%d\n", listenfd);

return -1;

}

curfds &#61; 1;

printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);

for (;;) {

/* 等待有事件发生 */

nfds &#61; epoll_wait(kdpfd, events, curfds, -1);

if (nfds &#61;&#61; -1)

{

perror("epoll_wait");

continue;

}

/* 处理所有事件 */

for (n &#61; 0; n

{

if (events[n].data.fd &#61;&#61; listenfd)

{

connfd &#61; accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);

if (connfd <0)

{

perror("accept error");

continue;

}

sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);

printf("%d:%s", &#43;&#43;acceptCount, buf);

if (curfds >&#61; MAXEPOLLSIZE) {

fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);

close(connfd);

continue;

}

if (setnonblocking(connfd) <0) {

perror("setnonblocking error");

}

ev.events &#61; EPOLLIN | EPOLLET;

ev.data.fd &#61; connfd;

if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) <0)

{

fprintf(stderr, "add socket &#39;%d&#39; to epoll failed: %s\n", connfd, strerror(errno));

return -1;

}

curfds&#43;&#43;;

continue;

}

// 处理客户端请求

if (handle(events[n].data.fd) <0) {

epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);

curfds--;

}

}

}

close(listenfd);

return 0;

}

int handle(int connfd) {

int nread;

char buf[MAXLINE];

nread &#61; read(connfd, buf, MAXLINE);//读取客户端socket流

if (nread &#61;&#61; 0) {

printf("client close the connection\n");

close(connfd);

return -1;

}

if (nread <0) {

perror("read error");

close(connfd);

return -1;

}

write(connfd, buf, nread);//响应客户端

return 0;

}

编译

编译和启动服务端

gcc epollserver.c -o epollserver

./epollserver

总结

以上就是这篇文章的全部内容了&#xff0c;希望本文的内容对大家的学习或者工作具有一定的参考学习价值&#xff0c;谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接



推荐阅读
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
author-avatar
zws3504075
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有