我们可以使用perror函数将错误信息打印到标准错误输出中,或者使用strerror函数将错误代码转换为错误信息字符串。在网络编程中,处理网络连接、连接收发数据等经常会涉及到errno的处理。...,需要对这些errno忽略,如果是其他错误,则需要执行错误回调或者直接处理错误。...,需要等待下一次读写事件再尝试读写,非阻塞模式下可以继续尝试读写ECONNRESET 或 EPIPE:表示连接被重置或对端关闭了连接,需要重新建立连接ENOTCONN:表示连接未建立或已断开,需要重新建立连接...在接受连接、建立连接和连接读写阶段可能会遇到多种 errno,如 EINTR、EAGAIN、EWOULDBLOCK、ECONNRESET、EPIPE、ENOTCONN、ETIMEDOUT、ECONNREFUSED...、EINVAL 等,需要对一些 errno 进行忽略,对于其他错误则需要执行错误回调或者直接处理错误。
本文以连接错误ECONNREFUSED为例,看看nodejs对错误处理的过程。 假设我们有以下代码 1. const net = require('net'); 2....r = connect(uv__stream_fd(handle), addr, addrlen); 5. } while (r == -1 && errno == EINTR); 6....// 连接错误,判断错误码 7....if (r == -1 && errno != 0) { 8. // 还在连接中,不是错误,等待连接完成,事件变成可读 9....else if (errno == ECONNREFUSED) 12. // 连接被拒绝 13.
,通常用errno(标准错误号,定义在errno.h中) Error number. ... { int fd; extern int errno; if((fd = open("/dev/dsp",O_WRONLY)) < 0) {... printf("errno=%d\n",errno); } exit(0); } 如果dsp设备忙的话errno值将是16。 ...errno.h中定义的错误代码值如下: 查 看错误代码errno是调试程序的一个重要方法。...> int main(void) { int fd; extern int errno; if((fd = open("/dev/dsp",O_WRONLY
TCP想取消一个已有的连接; 3....client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置...= 54 #defineECONNRESET 54/* Connection reset by peer */ 当一个进程向某个已收到RST的套接字执行读操作时,(此时读操作返回ECONNRESET...错误) 抓包信息如下: 上述情况会引发一个问题:服务器主机进程终止或者崩溃后重启,客户端在不write的情况下不会知道,read会返回ECONNRESET错误或者超时; 解决方法用select: 1....如果对端TCP发送一个RST(对端主机崩溃并重新启动),那么该套接字变为可读,并且read返回-1,而errno中含有确切的错误码; 这个问题在select详解中讲述 情况三: 修改客户端程序如下,服务端不变
2、非阻塞I/O 我们可以使用 fcntl(fd, F_SETFL, flag | O_NONBLOCK); 将套接字标志变成非阻塞,调用recv,如果设备暂时没有数据可读就返回-1,同时置errno为...参数2:读集合,关心可读事件; 套接口缓冲区有数据可读 对等连接的写一半关闭。...即接收到FIN段,读操作将返回0 如果是监听套接口,已完成连接队列不为空时。 套接口上发生了一个错误待处理,错误可以通过getsockopt指定SO_ERROR选项来获取。...(连接一旦建立就可写) 对等连接的读一半关闭。即收到RST段之后,再次调用write操作。 套接口上发生了一个错误待处理,错误可以通过getsockopt指定SO_ERROR选项来获取。...注意当select阻塞返回后,此时调用accept 接收连接是不会阻塞的,直接返回已连接套接字,可以认为是select 提前阻塞了。
3.效率并不是绝对的,当连接率高,断开和连接频繁时,select不一定比epoll差。所以要根据具体场合使用。 epoll的两种模式,电平触发和边沿触发。...: %d)\n",strerror(errno),errno); exit(0); } if (listen(listen_fd, LISTENQ)...== listen_fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。...)) < 0) { if (errno == ECONNRESET) { close(socket_fd);...第一次学epoll时,容易错误的认为epoll也可以实现并发,其实正确的话是epoll可以实现高性能并发服务器,epoll只是提供了IO复用,在IO“并发”,真正的并发只能通过线程进程实现。
增加socket函数的错误处理 之前的程序中,使用的socket相关的api都没有进行错误判断,一旦某个函数发生错误,程序可能就会崩溃,所以我们需要给原生api包裹一层,添加错误判断,就像下面这样:...*)vptr; nleft = n; while (nleft > 0) { if ( (nread = read(fd, ptr, nleft)) < 0) { if (errno =...,就fork一个子进程来处理这个连接。...服务器主机崩溃后重启,此时再收到客户端发送的信息,会给客户端返回RST,然后导致正阻塞在redline的客户返回ECONNRESET错误。...0) { #ifdef EPROTO if (errno == EPROTO || errno == ECONNABORTED) #else if (errno == ECONNABORTED
}; 结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件,其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器...表示对应的文件描述符可以读; EPOLLOUT:表示对应的文件描述符可以写; EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来); EPOLLERR:表示对应的文件描述符发生错误...以代码来说明问题: 首先给出server的代码,需要说明的是每次accept的连接,加入可读集的时候采用的都是LT模式,而且接收缓冲区是5字节的,也就是每次只接收5字节的数据: #include<iostream...) < 0) continue; if((n = read(sockfd, line, MAXLINE)) < 0) { if(errno ==...ECONNRESET) { close(sockfd);
为什么客户端的错误提示跟这里的不一样呢?...这正说明epoll 处理效率比poll和select 都高,因为处理得快,来一个连接就accept一个,当服务器端accept 完第1019个连接,再次accept 时会因为文件描述符总数超出限制,打印错误提示...,而此时客户端虽然已经创建了第1020个sock,但在connect 过程中发现对等方已经退出了,故打印错误提示,连接被对等方重置。...如果服务器端处理得慢的话,那么客户端会connect 成功1021个连接,然后在创建第1022个sock 的时候出错,打印错误提示:socket: Too many open files,当然因为文件描述符的限制...,服务器端也只能从已完成连接队列中accept 成功1019个连接。
looping"; 39 looping_ = false; 40} poller_->poll利用epoll分离网络事件,然后接着处理分离出来的网络事件,每一个客户端socket对应一个连接..._) readCallback_(receiveTime); 45 } 46 if (revents_ & POLLOUT) 47 { 48 //如果是连接状态服的...当然,这里利用了Channel对象的“多态性” 如果是普通socket,可读事件就会调用预先设置的回调函数; 但是如果是侦听socket,则调用Aceptor对象的handleRead()来接收新连接...ing when you can't" in libev's doc. 27 // By Marc Lehmann, author of livev. 28 if (errno...33 if (errno == EPIPE || errno == ECONNRESET) 34 { 35
注意:size是数量的最大值,不是fd的最大值 当创建好epoll句柄后,它就是会占用一个fd值,所以在使用完epoll后,必须使用close()关闭,否则可能导致fd被耗尽。...正常关闭); EPOLLOUT: 表示对应的文件描述符可以写; EPOLLPRI: 表示对应的文件描述符有紧急的数据可读(这里表示有带外数据到来); EPOLLERR: 表示对应的文件描述符发生错误...#include #include #include #include #include <errno.h...== listenfd) //有新的连接 { clilen = sizeof(struct sockaddr_in);..., 0)) < 0) { if(errno == ECONNRESET) {
我们前面说到sockfd其实同真正的FD是一样的。都是LINUX下的一个打开的设备描述符。内核通过这个描述符进行I/O操作。...2)非阻塞I/O,在将套接口设置为非阻塞方式下,内核就让请求的I/O操作在没有数据的情况直接返回一个错误,不再等特。显然这种操作需要不停的尝试,消耗非常多的CPU。 ?...虽然是增强版本,但是也是适用于特定场景下的,这个特定场景是大量并发连接中只有少量活跃的情况。在这种情况下如何避免扫描FD集合的开销和如何有效触发活跃I/O操作。...因此,对一个大并发量的应用服务器,如果有很多连接,但一时时段的活跃连接并不多时,采用EPOLL效率非常高。...== ECONNRESET) { close(sockfd); events
#include // 成功,返回代表新连接的描述符,错误返回-1,同时错误码设置在errno int accept(int sockfd,struct sockaddr*...errno内。...理解accept的关键点是,它会创建一个新的Socket,这个新的Socket来与对端运行connect()的对等Socket进行连接,如下图所示: 接下来,我们就进入Linux内核源码栈吧 accept...(queue); newsk = req->sk; /* fastopen 判断逻辑 */ ...... /* 返回新的sock,也就是accept派生出的和client端对等的那个sock *...由代码得知在accept超时时候返回(errno)的是EAGAIN而不是ETIMEOUT。
在普通模式下,双方可以正常建立连接,当server端作为daemon启动时,则第一次启动成功,之后再启动, listen 会连接报 ENOTSUPP 错误,导致启动失败。..., (struct sockaddr *)&un, len) < 0) { 17 err = errno; 18 printf ("connect failed\n")...; 25 errout: 26 close (fd); 27 errno = err; 28 return rval; 29 } 30 31 32 int serv_listen...opend: listen failed, errno 95 Jan 17 00:24:44 localhost opend: serv_listen error: Operation not supported...failed, errno 95 Jan 17 00:43:11 localhost opend: serv_listen error: Operation not supported 设置成功了,但还是不行
前言 当UNIX函数出现错误时,常常返回一个负值,而且整型变量errno通常被设置为含有附加信息的一个值。...关于这点可以看我的:段错误?打的就是段错误! 而对于非致命性错误,有课可以较为妥善的处理。大多数非致命性错误在本质上是暂时的,例如资源短缺,当系统中活动较少时,这种出错很可能就不会发生。...例如,假设-个 出错表明一个 网络连接不再起作用, 那么应用程序可以在短时间延迟后重建该连接。某些应用使用指数补偿算法,在每次重复中等待更长时间。...假定一个读操作,它被中断,我们要恢复它: again: if(n= read(fd, buf, BUFSIZE)) < 0) if (errno == EINTR) goto again;/* just...errno: 16 Device or resource busy errno: 17 File exists errno: 18 Invalid cross-device
client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置...,signal(SIGPIPE, SIG_IGN); 如果SIGPIPE信号没有导致进程异常退出(捕捉信号/忽略信号),write返回-1并且errno为EPIPE(Broken pipe)。...可以选择关闭某个方向或者同时关闭两个方向,shutdown how = 0 or how = 1 or how = 2 (SHUT_RD or SHUT_WR or SHUT_RDWR),后两者可以保证对等方接收到一个...下面使用shutdown 修改客户端程序,在前面讲过的使用select函数修改后的客户端程序基础上,修改很小一部分: if (FD_ISSET(fd_stdin, &rset)) { if (...但因为我们已经设置了忽略SIGPIPE信号,所以服务器端进程不会被终止,但客户端也会出错,因为回到while循环开头,select阻塞等待时发现套接字的读端已经关闭,所以不能再关心可读事件了,select会返回-1,错误码是
#include // 成功,返回代表新连接的描述符,错误返回-1,同时错误码设置在errno int accept(int sockfd,struct sockaddr*...errno内。...理解accept的关键点是,它会创建一个新的Socket,这个新的Socket来与对端运行connect()的对等Socket进行连接,如下图所示: ?...由代码得知在accept超时时候返回(errno)的是EAGAIN而不是ETIMEOUT。...多个fd监听同一个端口号,在内核中做负载均衡(Sharding),将accept的任务分散到不同的线程的不同Socket上(Sharding),毫无疑问可以利用多核能力,大幅提升连接成功后的Socket
与select/poll相比,epoll的优点体现在以下三个方面: 1) 支持进程打开大数目的文件描述符(FD) select最大的缺点是一个进程所打开的文件描述符是有一定限制的,默认值是2048,这对于那些需要支持成千上万连接数目的服务器来说显然是太少了...如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表....idle -connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当我们遇到大量的idle- connection(例如WAN环境中存在大量的慢速连接...if(errno == EINTR) return -1; // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满, // 在这里做延时后再重试...== ECONNRESET) { close(sockfd);
select失败时返回-1并设置errno 如果select 等待期间,程序接收到信号,则select立即返回-1,并设置errno为EINTR。...此时我们可以无阻塞地对该socket,并且读操作返回的字节数大于0 socket通信的对方关闭连接,此时读操作返回0 监听socket上有新的连接请求 socekt上有未处理的错误,此时我们可以使用getsockopt...来读取和清除该错误。...对写操作被关闭的socket执行写操作将出发一个SIGPIPE信号 socket使用非阻塞connect连接成功或者失败之后 socket上有未处理的错误,此时我们可以使用getsockopt来读取和清除该错误...当活动连接比较多的时候,回调函数被触发得过于频繁,而降低效率。 所以,epoll_wait适用于连接数量多,但活动连接较少的情况。 ---- 参考资料: 《Linux高性能服务器编程》
boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件和镜像文件。...预定义的文件描述符: 0: 标准输入,对应于已打开的标准输入设备(键盘) 1: 标准输出,对应于已打开的标准输出设备(控制台) 2: 标准错误,对应于已打开的标准错误输出设备(控制台) (运行程序在...返回值: 成功:返回实际写入的字节数 失败:返回-1,设置错误号errno,用strerror(errno)查看 注意: 从文件当前指针位置开始写入。文件刚打开时从文件指针指向文件头。...,reason :%s\n",strerror(errno)); exit(-1); } count = write(fd, buffer, strlen(buffer)); printf...int ioctl(int fd, int cmd,[int *argdx, int argcx]); fd是用户程序打开设备时使用open函数返回的文件标示符, cmd是用户程序对设备的控制命令
领取专属 10元无门槛券
手把手带您无忧上云