网络I/O

网络I/O

网络IO部分经常会被问到同步/异步、阻塞/非阻塞相关知识点,下面来总结一下我对这些知识点的理解。
网络IO有两个阶段第一个是数据就绪,第二阶段是数据读写

数据就绪

数据就绪可以理解为数据有没有到达。那我们该怎么判断数据有没有到达呢?可以通过TCP接受缓冲区有没有数据到达来判断数据就绪,如果有数据那么就说明有数据到达了,如果TCP接受缓冲区没有数据那么说明没有数据到达。
数据就绪阶段又可以分为两个知识点,阻塞/非阻塞。
阻塞:调用了读写(I/O)方法的线程进入阻塞状态。
通俗的来说就是当我调用recv(read),而TCP缓冲区里没有数据时recv就会阻塞(recv默认是阻塞的)。
非阻塞:不会改变线程的状态,通过返回值来判断。
我们可以通过设置sockfd为O_NONBLOCK来设为非阻塞。那么可以通过它的返回值来判断,返回值如下:

int size = recv(sockfd, buf, 1024, 0);
size == -1 表示出错,没有读到数据或者是调用的系统函数失败了(EINTR, EAGAIN, EWOULDBLOCK)
size == 0 读取到数据的末尾,对方连接关闭
size > 0 读取到了多少数据,size就是读到的数据的长度了
EINTR:产生了信号吧函数中断以后会返回的错误号(如过有一个信号来,由于信号的优先级高就会去执行信号处理函数)
EAGAIN:没有读到数据,让我再读一次就会返回这两个错误号

数据读写

数据的读写也有两个知识点为同步/异步。
同步:首先初始化一个数组用来保存缓冲区里的内容,再用recv读数据,通过得到的size来判断独到的数据,数据就会通过应用程序从内核态读到用户态。这就是同步的概念。
优点:写起来简单易懂。
缺点:效率没有异步高,因为数据由应用程序搬,使用的时间是用户的时间。

char buf[1024] = {0};
int size = recv(sockfd, buf, 1024, 0);
...
if (size > 0) {
	...
}

异步:还是需要一个数组来存储缓冲区里的内容,但是要存储的数据不需要由我们来进行搬运而是由内核帮我们搬,搬好以后就通知我们数据已经装好了我们再进行处理就可以了。
Linux异步接口:aio_read()/aio_write()
优点:内核自己帮我们搬数据,而我们可以继续往下的操作,搬好以后通知我们,我们再去处理数据。效率比同步高。
缺点:编程麻烦,调用异步接口然后执行其他内容,数据到了再去处理数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值