转自:https://www.cnblogs.com/sunziying/p/6501045.htmlhtml
阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的确认时,则connect返回.不然的话一直阻塞.
非阻塞方式,connect将启用TCP协议的三次握手,可是connect函数并不等待链接创建好才返回,而是当即返回。返回的错误码为EINPROGRESS,表示正在进行某种过程. 缓存
对于阻塞方式的倾听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 //设备控制接口函数socket
int b_on = 1; ioctl (fd, FIONBIO, &b_on);
对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返回。当socket缓冲区中的数据量小于指望读取的数据量时,返回实际读取的字节数。当sockt的接收缓冲区中的数据大于指望读取的字节数时,读取指望读取的字节数,返回实际读取的长度。
对于非阻塞socket而言,socket的接收缓冲区中有没有数据,read调用都会马上返回。接收缓冲区中有数据时,与阻塞socket有数据的状况是同样的,若是接收缓冲区中没有数据,则返回错误号为EWOULDBLOCK,表示该操做原本应该阻塞的,可是因为本socket为非阻塞的socket,所以马上返回,遇到这样的状况,能够在下次接着去尝试读取。若是返回值是其它负值,则代表读取错误。函数
所以,非阻塞的read调用通常这样写:性能
if ((nread = read(sock_fd, buffer, len)) < 0) { if (errno == EWOULDBLOCK) { return 0; //表示没有读到数据 } else return -1; //表示读取失败 } else return nread;读到数据长度
而对于阻塞Socket而言,若是发送缓冲区没有空间或者空间不足的话,write操做会直接阻塞住,若是有足够空间,则拷贝全部数据到发送缓冲区,而后返回.spa
对于写操做write,原理是相似的,非阻塞socket在发送缓冲区没有空间时会直接返回错误号EWOULDBLOCK,表示没有空间可写数据,若是错误号是别的值,则代表发送失败。若是发送缓冲区中有足够空间或者是不足以拷贝全部待发送数据的空间的话,则拷贝前面N个可以容纳的数据,返回实际拷贝的字节数。
非阻塞的write操做通常写法是:htm
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;
ERROR IN PROGRESS 对象
ERROR WOULD BLOCK
功能描述:根据【文件描述词】来操做文件的特性。
头文件:
#include <unistd.h>
#include <fcntl.h>
函数原型:
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
描述:
fcntl()针对(文件)描述符提供控制.参数fd是被参数cmd操做(以下面的描述)的描述符. 针对cmd的值,fcntl可以接受第三个参数(arg)
fcntl函数有5种功能:
1.复制一个现有的描述符(cmd=F_DUPFD).
2.得到/设置文件描述符标记(cmd=F_GETFD或F_SETFD).
3.得到/设置文件状态标记(cmd=F_GETFL或F_SETFL).
4.得到/设置异步I/O全部权(cmd=F_GETOWN或F_SETOWN).
5.得到/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).
cmd 选项:
F_DUPFD:返回一个以下描述的(文件)描述符:
(1)最小的大于或等于arg的一个可用的描述符
(2)与原始操做符同样的某对象的引用
(3)若是对象是文件(file)的话,返回一个新的描述符,这个描述符与arg共享相同的偏移量(offset)
(4)相同的访问模式(读,写或读/写)
(5)相同的文件状态标志(如:两个文件描述符共享相同的状态标志)
(6)与新的文件描述符结合在一块儿的close-on-exec标志被设置成交叉式访问execve(2)的系统调用
F_GETFD:取得与文件描述符fd联合close-on-exec标志,相似FD_CLOEXEC.若是返回值和FD_CLOEXEC进行与运算结果是0的话,文件保持交叉式访问exec(), 不然若是经过exec运行的话,文件将被关闭(arg被忽略)
F_SETFD:设置close-on-exec旗标。该旗标以参数arg的FD_CLOEXEC位决定。
F_GETFL:取得fd的文件状态标志,如同下面的描述同样(arg被忽略)
F_SETFL:设置给arg描述符状态标志,能够更改的几个标志是:O_APPEND, O_NONBLOCK,O_SYNC和O_ASYNC。
F_GETOWN:取得当前正在接收SIGIO或者SIGURG信号的进程id或进程组id,进程组id返回成负值(arg被忽略)
F_SETOWN:设置将接收SIGIO和SIGURG信号的进程id或进程组id,进程组id经过提供负值的arg来讲明,不然,arg将被认为是进程id
F_GETFL和F_SETFL的标志以下面的描述:
O_NONBLOCK:非阻塞I/O;若是read(2)调用没有可读取的数据,或者若是write(2)操做将阻塞,read或write调用返回-1和EAGAIN错误 O_APPEND :强制每次写(write)操做都添加在文件大的末尾,至关于open(2)的O_APPEND标志
O_DIRECT :最小化或去掉reading和writing的缓存影响.系统将企图避免缓存你的读或写的数据.
若是不可以避免缓存,那么它将最小化已经被缓存了的数 据形成的影响.若是这个标志用的不够好,将大大的下降性能
O_ASYNC :当I/O可用的时候,容许SIGIO信号发送到进程组,例如:当有数据能够读的时候
注意: 在修改文件描述符标志或文件状态标志时必须谨慎,先要取得如今的标志值,而后按照但愿修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭之前设置的标志位。
fcntl的返回值: 与命令有关。若是出错,全部命令都返回-1,若是成功则返回某个其余值。下列三个命令有特定返回值:F_DUPFD,F_GETFD,F_GETFL以及F_GETOWN。第一个返回新的文件描述符,第二个返回相应标志,最后一个返回一个正的进程ID或负的进程组ID。