epoll socket 服务端中read和write的返回值讨论

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

    先贴一段代码,代码很简单要看过epoll如何使用,都应该能看懂。

    这是服务端程序:

#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>#define MAXLINE		10
#define OPEN_MAX	100
#define LISTENQ		20
#define SERV_PORT	5555
#define INFTIM		1000void setnonblocking(int sock)
{int opts;opts = fcntl(sock, F_GETFL);if(opts < 0) {perror("fcntl(sock, GETFL)");exit(1);}opts = opts | O_NONBLOCK;if(fcntl(sock, F_SETFL, opts) < 0) {perror("fcntl(sock, SETFL, opts)");exit(1);}
}int main(int argc, char *argv[])
{printf("epoll socket begins.\n");int i, maxi, listenfd, connfd, sockfd, epfd, nfds, on = 1;ssize_t n;char line[MAXLINE];socklen_t clilen;struct epoll_event ev, events[20];epfd = epoll_create(256);struct sockaddr_in clientaddr;struct sockaddr_in serveraddr;listenfd = socket(AF_INET, SOCK_STREAM, 0);setnonblocking(listenfd);ev.data.fd = listenfd;ev.events = EPOLLIN | EPOLLET;epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));bzero(&serveraddr, sizeof(serveraddr));serveraddr.sin_family = AF_INET;char *local_addr = "0.0.0.0";inet_aton(local_addr, &(serveraddr.sin_addr));serveraddr.sin_port = htons(SERV_PORT);int ret = bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));if(ret < 0){printf("%s\n", "bind error!");exit(-1);}listen(listenfd, LISTENQ);maxi = 0;for(; ;) {nfds = epoll_wait(epfd, events, 20, 500);for(i = 0; i < nfds; ++i) {if(events[i].data.fd == listenfd) {printf("accept connection, fd is %d\n", listenfd);connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clilen);if(connfd < 0) {perror("connfd < 0");exit(1);}setnonblocking(connfd);char *str = inet_ntoa(clientaddr.sin_addr);printf("connect from %s\n", str);ev.data.fd = connfd;ev.events = EPOLLIN | EPOLLET;epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);}else if(events[i].events & EPOLLIN) {sockfd = events[i].data.fd;n = read(sockfd, line, MAXLINE);if(n < 0 && errno == EAGAIN){printf("%s\n", "数据已经读完,没有更多的数据可以读了。");}else if(n == 0) //errno {printf("%s\n", "客户端断开连接。");epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &ev);}			else if(n <= 0)					{printf("%s\n错误代码为%d", "读出错。", errno);epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &ev);}else{					 printf("%s\n", line);memset(line, 0, MAXLINE);n = write(sockfd, "hello client!", strlen("hello client!"));if(n < 0 && errno == EAGAIN){printf("%s\n", "系统缓冲区数据已写满。");}else if(n <= 0){printf("%s\n错误代码为%d", "客户端断开连接或出错。", errno);						}					else{					ev.data.fd = sockfd;ev.events = EPOLLIN | EPOLLET;					epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);}}				}else if(events[i].events & EPOLLOUT) {}}}
}

 

    客户端程序:

    可以不用代码写客户端,用telnet连接就行。

telnet localhost 5555

 

#!/usr/bin/pythonfrom socket import *
from time import sleephost = gethostname()
addr = (host, 5555)sockCli = socket()sockCli.connect(addr)while True:sockCli.sendall("sadf")data = sockCli.recv(1024)print datasleep(1)sockCli.close()

 

这段服务端的代码展示的是用,epoll写的一个简单的服务程序, ET非阻塞模式。

关于read的返回值:

    1、返回值n=-1, errno = EAGAIN;当返回值等于你要读取的数据时,说明你还有数据要读。 当数据量比较大,多次读数据的时候非阻塞read的返回值为-1,errno值为11(EAGAIN)时,这个 并不是发生了错误,而是数据已经被读完,这个时候停止读数据就好了。阻塞模式不会这样,因为当没有数据的时候,read就阻塞了。

    2、返回值n=0, errno = 0。说明客户端已经关闭了。经过测试即使没有数据的时候,阻塞的read就阻塞,非阻塞的read时为第一种情况。只有客户端关闭时返回0(socket fd是这样其他io流为测试) 。这个时候就就不要再注册事件了,从队列中删除这个fd吧。而且当客户端断开时,epoll会主动通知一个EPOLLIN事件。

    3、返回值n=-1,errno != EAGAIN;时是错了,看一下错误码是多吧。

关于write的返回值:

    1、返回值n=-1,errno = EAGAIN时; 说明系统缓冲区已经满了,不能再写进去了。当write为阻塞时不会返回这个错误,会阻塞掉。

    2、返回值n<=0时;客户端断开连接或出错。

何时系统会通知一个写事件:

    对于LT 模式,如果注册了EPOLLOUT,只要该socket可写(发送缓冲区)未满,那么就会触发EPOLLOUT。

    对于ET模式,如果注册了EPOLLOUT,只有当socket从不可写变为可写的时候,会触发EPOLLOUT。

    上面server端的例子,当你要写入的数据比较大的时候,可能就会有困扰了,如何写入的数据量较大,把系统缓冲区写满了,如果write设置是阻塞的,那就会阻塞了。这可能不是我们想要的。

    这个时候就需要注册写事件,自己在应用层加个发送缓冲区,需要发送数据的时候,就写到应用层的发送缓冲区。触发write事件的时候,从缓冲区写入socket。

 

转载于:https://my.oschina.net/u/2255341/blog/650661

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

异常处理—错误抛出机制

错误抛出机制&#xff1a; 把可能出现异常的代码写在try{}里&#xff0c;使用catch(){}设置一些异常陷阱来捕获异常。例如&#xff1a; 没有异常处理时异常的抛出机制&#xff1a; 为什么出现异常会在控制台上显示打印红色的异常呢&#xff1f;这是因为其实main方法外面还有一个…

【ArcGIS Pro风暴】Data Interoperability Tools快速将CASS等高线dwg转为shp案例教程

ArcGSI提供了多种将cass制作的dwg格式的地形图数据转为shp矢量格式。在ArcMap中的转换方法可以参考: CAD格式数据转ArcGIS数据方法总结,本文以案例的形式,讲解在ArcGIS Pro2.5中如何借助Data Interoperability Tools中的Quick Import工具将dwg格式的等高线完美转换为shp,转…

.Net 之时间轮算法(终极版)

关于时间轮算法的起始我也认真的看了时间轮算法相关&#xff0c;大致都是如下的一个图在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述个人认为的问题大部分文章在解释这个为何用时间轮的时候都再说假设我们现在有一个很大的数组&#xff0c;专门用…

Unity中Instantiate一个prefab时需要注意的问题

在调用Instantiate()方法使用prefab创建对象时&#xff0c;接收Instantiate()方法返回值的变量类型必须和声明prefab变量的类型一致&#xff0c;否则接收变量的值会为null. 比如说&#xff0c;我在脚本里面定义:public GameObject myPrefab; 那么在使用这个myPrefab做Instantia…

C语言试题143之写一个函数,求一个字符串的长度,在 main 函数中输入字符串,并输出其长度

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:写一个函数,求一个字符串的…

无人机影像去雾批处理神器使用方法(附神器下载)

文章目录 1. 软件特点:2. 影像去雾批处理演示3. 神器下载地址1. 软件特点: (1)设置简单。只需要设置输入输出路径。 (2)支持多级路径。路径下可以有子路径,输出文件夹结构与输入文件夹结构一致 (3)支持并行处理。可同时打开几个窗口,只需要设置同样路径即可 2. 影…

《Redis官方文档》Redis调试指南

原文链接 译者&#xff1a;Adeline Redis开发过程中十分注重其稳定性&#xff1a;我们尽一切努力来保证每一个版本的稳定&#xff0c;不出现突然崩溃等情况。但是即使在我们百分百的努力下&#xff0c;仍然没办法保证百分百的无bug。 Redis出现崩溃时&#xff0c;会生成一…

Java基础系列8:Java的序列化与反序列化(修)

一 简介 对象序列化就是把一个对象变成二进制的数据流的一种方法&#xff0c;通过对象序列化可以方便地实现对象的传输和存储。 把对象转换为字节序列的过程称为对象的序列化 把字节序列恢复为对象的过程称为对象的反序列化 对象的序列化主要有两种用途&#xff1a; 1&#xff…

[转]nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件

文章目录 前言一、nginx简介 1. 什么是 nginx 和可以做什么事情2.Nginx 作为 web 服务器3. 正向代理4. 反向代理5. 负载均衡6.动静分离二、Nginx 的安装(Linux:centos为例) 1. 准备工作2. 开始安装3. 运行nginx4. 防火墙问题三、 Nginx 的常用命令和配置文件 1. Nginx常用命令 …

在 .NET 6 中使用 Startup.cs 更简洁的方法

如果您在关注 .NET 6&#xff0c;那么您应该知道&#xff0c;在 .NET 6 项目中&#xff0c;没有 Startup.cs 文件&#xff0c;现在使用了 Program.cs 文件来完成统一的配置。我之前发了一篇使用在 .NET 6 项目中使用 Startup.cs 的文章。在 .NET 6 项目中使用 Startup.cs能否能…

【ArcGIS Pro微课1000例】0005:ArcGIS Pro 2.5基于矢量数据制作拉伸三维地图案例

ArcGIS Pro 2.5中,可以基于某个字段,对矢量数据进行拉伸,制作精美的三维地图。本文以中国省级行政区划数据为例,基于面积字段制作3d地图。 文章目录 1. 新建局部场景2. 地图符号化3. 三维矢量地图制作1. 新建局部场景 打开ArcGIS Pro 2.5,新建局部场景项目,并保存。 2. …

C语言试题144之编写函数输入,输出 5 个学生的数据记录。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:编写 input()和 output()函数…

第十一次实验总结

知识点总结&#xff1a; 指针、数组和地址间的关系 数组的基地址是在内存中存储数组的起始位置&#xff0c;它是数组中第一个元素&#xff08;下标为0&#xff09;的地址&#xff0c;因此数组名本身是一个地址即指针值。 指针是以地址作为值的变量&#xff0c;而数组名的值是一…

Python统计列表中的重复项出现的次数的方法

本文实例展示了Python统计列表中的重复项出现的次数的方法&#xff0c;是一个很实用的功能&#xff0c;适合Python初学者学习借鉴。具体方法如下&#xff1a; 对一个列表&#xff0c;比如[1,2,2,2,2,3,3,3,4,4,4,4]&#xff0c;现在我们需要统计这个列表里的重复项&#xff0c;…

分布式(一致性协议)之领导人选举( DotNext.Net.Cluster 实现Raft 选举 )

分布式(一致性协议)之领导人选举( DotNext.Net.Cluster 实现Raft 选举 )继分布式锁之后的又一高可用技术爽文之分布式领导选举 或者说 分布式一致性协议的实现分布式选举是实现高可用的必备技术&#xff0c;想实现主从&#xff0c;就必须得有选举的策略&#xff0c;有主从才会有…

投巧解决JavaScript split方法出现空字符的问题

直接使用split&#xff0c;前后各有一个“”值。 >> var str,a,b,c,d,e,f,; >> str.split(,);//(8) ["", "a", "b", "c", "d", "e", "f", ""]临时方法&#xff1a;split后&…

C语言试题146之反向输出一个链表

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:反向输出一个链表 2 、温馨提…

【ArcGIS Pro微课1000例】0006:ArcGIS Pro 2.5三维显示DEM数字高程模型

通过ArcGIS的学习,我们知道,ArcScene可以实现二维数据的三维显示,是将二维数据(例如DEM)进行自定义表面浮动拉伸。那么ArcGIS Pro中能不能实现DEM的三维显示呢? ArcScene三维显示结果: 目前所采用的ArcGIS Pro 2.5版本还不能直接将DEM进行三维显示,我们的做法是参照Ar…

中国古代历朝首都一览

【五帝时期】&#xff08;约公元前26世纪初—公元前2070年&#xff09; 『黄帝』有熊&#xff08;今河南郑州新郑&#xff09; 『颛顼』帝丘&#xff08;今河南濮阳&#xff09; 『帝喾』帝丘&#xff08;今河南濮阳&#xff09;、西亳&#xff08;今河南洛阳偃师西&#xff09…

程序员的自我修养:有助于提高沟通能力的7本书

直接影响工作效率的四种能力&#xff1a;沟通能力、自学能力、自我管理能力、问题解决能力。提高沟通能力&#xff0c;是程序员提高自我修养的必要条件。相信很多人跟我一样&#xff0c;性格内向&#xff0c;信仰技术&#xff0c;很少有跟人说话的愿望&#xff0c;只是想看代码…