linux 非阻塞socket,容器内执行docker命令

大家好,如果您还对linux 非阻塞socket不太了解,没有关系,今天就由本站为大家分享linux 非阻塞socket的知识,包括容器内执行docker命令的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

linux网络编程中阻塞和非阻塞socket的区别

阻塞socket和非阻塞socket的区别:

1、读操作

对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返回。当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数。当sockt的接收缓冲区中的数据大于期望读取的字节数时,读取期望读取的字节数,返回实际读取的长度。

对于非阻塞socket而言,socket的接收缓冲区中有没有数据,read调用都会立刻返回。接收缓冲区中有数据时,与阻塞socket有数据的情况是一样的,如果接收缓冲区中没有数据,则返回错误号为EWOULDBLOCK,表示该操作本来应该阻塞的,但是由于本socket为非阻塞的socket,因此立刻返回,遇到这样的情况,可以在下次接着去尝试读取。如果返回值是其它负值,则表明读取错误。

因此,非阻塞的rea调用一般这样写:

if((nread= read(sock_fd, buffer, len))< 0)

{

if(errno== EWOULDBLOCK)

{

return 0;//表示没有读到数据

}else return-1;//表示读取失败

}else return nread;读到数据长度

2、写操作

对于写操作write,原理是类似的,非阻塞socket在发送缓冲区没有空间时会直接返回错误号EWOULDBLOCK,表示没有空间可写数据,如果错误号是别的值,则表明发送失败。如果发送缓冲区中有足够空间或者是不足以拷贝所有待发送数据的空间的话,则拷贝前面N个能够容纳的数据,返回实际拷贝的字节数。

而对于阻塞Socket而言,如果发送缓冲区没有空间或者空间不足的话,write操作会直接阻塞住,如果有足够空间,则拷贝所有数据到发送缓冲区,然后返回.

非阻塞的write操作一般写法是:

int write_pos= 0;

int nLeft= nLen;

while(nLeft> 0)

{

int nWrite= 0;

if((nWrite= write(sock_fd, data+ write_pos, nLeft))<= 0)

{

if(errno== EWOULDBLOCK)

{

nWrite= 0;

}else return-1;//表示写失败

}

nLeft-= nWrite;

write_pos+= nWrite;

}

return nLen;

3、建立连接

阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的确认时,则connect返回.否则的话一直阻塞.

非阻塞方式,connect将启用TCP协议的三次握手,但是connect函数并不等待连接建立好才返回,而是立即返回。返回的错误码为EINPROGRESS,表示正在进行某种过程.

4、接收连接

对于阻塞方式的倾听socket,accept在连接队列中没有建立好的连接时将阻塞,直到有可用的连接,才返回。

非阻塞倾听socket,在有没有连接时都立即返回,没有连接时,返回的错误码为EWOULDBLOCK,表示本来应该阻塞。

无阻塞的设置方法

方法一:fcntl

int flag;

if(flag= fcntl(fd, F_GETFL, 0)<0) perror("get flag");

flag|= O_NONBLOCK;

if(fcntl(fd, F_SETFL, flag)< 0)

perror("set flag");

方法二:ioctl

int b_on= 1;

ioctl(fd, FIONBIO,&b_on);

linux非阻塞的socket发送数据出现EAGAIN错误的处理方法

非阻塞套接字在Linux中允许应用程序执行网络调用并立即返回,而无需等待结果。这在C/S(客户端/服务器)模式下尤其有用,因为它们通常采用异步非阻塞模式进行操作。

然而,当设置O_NONBLOCK属性后,如果发送缓存已满,send函数将返回EAGAIN或EWOULDBLOCK错误。这种情况下,通过封装socket_send函数,可以尽量将数据发送完毕再返回实际发送的字节数。在socket_send函数中,当写缓冲已满且返回EAGAIN错误时,会等待并再次尝试发送。

若在发送大包数据时,客户端未及时调用recv函数接收数据,服务器可能会陷入死循环,持续调用send函数直至返回EAGAIN错误。为解决此问题,可采用以下方法之一:

增大tcp_sendspace值,使其大于发送数据的size参数。

在调用send前,使用setsockopt函数将SNDBUF设置为更大的值。

使用write函数替代send,因为write没有设置O_NDELAY或O_NONBLOCK属性。

在发送数据前,增加EPOLLOUT事件监听,确保在数据全部发送完毕后取消此监听。使用socket缓存结构体组织数据,将待发送数据放入缓存,并在触发EPOLLOUT事件时调用socket_send函数发送数据,确保所有数据发送完毕后清除EPOLLOUT事件。

综上所述,合理管理发送缓存和事件监听,可以有效处理非阻塞socket发送数据时可能出现的EAGAIN错误。

C++ socket非阻塞模式

一、前言

初期学习socket的时候,为了方便理解,使用默认的阻塞模式比较多。而实际做项目时,我们必须考虑程序的并发性,非阻塞模式在其中担任着很重要的角色,是必会的点之一。本文不对阻塞IO和非阻塞IO的概念做说明,不了解的请自行了解。下文代码以linux平台为例。

二、设置非阻塞模式

设置非阻塞模式,通过fcntl方法设置,为了保存socket其他设置,一般选择先获取 status flags,并在其基础上设置O_NONBLOCK属性,代码如下:

fcntl失败返回值为-1,同时errno会被设置成对应的错误码。(errno在此不做说明,不了解的自行了解。)考虑失败的情况,个人注意到网上有些例子(包括ss-libev项目)在 F_GETFL失败后,给了flags默认值,代码如下:

经过测试,默认情况下,flags得到的值为2,也就是O_RDWR读写,而 0对应的相关宏为O_RDONLY只读,明显不合理。个人感觉,对于一个正常的socket来说,F_GETFL出错的机会不大吧,至少我是没遇到过。如果实在出错了,还是建议走错误流程而不是给个默认值。

三、非阻塞server

server端通常在accept后,我们为客户端连接的fd设置为非阻塞。设置O_NONBLOCK后,recv和send发生了变化。默认阻塞模式下,recv在没有数据可以接收(对方未发数据,或者缓冲区的数据已读完对方没有继续发)情况下,recv会阻塞等待,直到下次有数据发送过来。而非阻塞模式下,recv在没有数据可以接收的时候, recv会直接返回-1,同时errno会被设置为EAGAIN/EWOULDBLOCK。同理,非阻塞send也会在对方缓冲区满的情况下直接返回-1并设置errno,而不是阻塞等待。非阻塞模式下server代码大致如下:

四、非阻塞client

client除了在send/recv,还可以在connect前设置非阻塞模式,这样在connect时候可以直接返回。

client非阻塞connect的时候,如果返回0表示连接成功,如果返回-1,则需要判断errno是否为EINPROGRESS,EINPROGRESS表示非阻塞连接不能立刻获取connect结果,后面可使用select/poll/epoll等对socket可写性进行判断,如果socket已可写,使用 getsockopt(iSocket, SOL_SOCKET, SO_ERROR,&err,&len)进行判断。。。好像挺麻烦是不是,但是我还是建议在大部分项目中connect前设置非阻塞(小工具之类的就无所谓了,项目中一定要保证效率)。如果使用阻塞模式,有可能的问题:

下面是个非阻塞connect的部分代码,使用select,至于poll/epoll请自行搜索代码,跟非阻塞逻辑无关:

阅读剩余
THE END