• MoonGod
    2019-09-27
    感觉这篇的解释和前面的比起来太不细致了…很多地方都没说明。老师能不能多一些说明啊

    作者回复: 我在代码里多加一些注释,可以看最新的代码

    https://github.com/froghui/yolanda

    
     4
  • 沉淀的梦想
    2019-09-30
    老师那个accept阻塞的实验,在我电脑(linux-4.18.0,ubuntu18.10)上的行为有点不太一样,无论是把listen_fd设置为阻塞还是非阻塞,sleep 5s还是10s或者更长,行为总是:accept成功获取到客户端连接,然后读取到客户端的RST

    作者回复: 这里举的一个例子,有可能在新的协议栈下有所改变,但是不管怎样,理论上的分析有可能导致阻塞,所以我们还是应该在平时编码中将监听套接字也设置为非阻塞的。

     2
     2
  • yusuf
    2019-09-29
    1、133行判断是否超过了文件描述符的最大值,如果超过了,就会报错。可以考虑使用动态分配的方式,但如果超过了1024的话,使用上一节中的poll来处理会更好些
    2、认为是考虑到对同一个fd的同一缓冲区进行读写操作,只用一个Buffer对象足够了
    
     2
  • 一天到晚游泳的鱼
    2019-10-05
    老师,我想请教一个问题就是, 当把一个描述符设置为非阻塞的之后,在该描述符上面的操作就会变成非阻塞的吗? 比如说把连接套接字设置为非阻塞的,send和recv就会变成非阻塞的吗?

    作者回复: 你的理解是对的。

    
     1
  • 刘晓林
    2019-10-04
    老师,有一个地方不是很明白。在连接套接字设为阻塞时,当客户端发送RST后,服务端在已完成连接队列删除了连接,accept阻塞。这时候如果有新连接进来了,为什么accept还是会阻塞呀?难道新连接进来一定要先select之后,accept才能取到连接好的套接字??

    作者回复: 不是一定需要select才可以 accept的。这里的例子主要是说明如果不给监听套集字设置为非阻塞,可能会引起的问题。

     1
     1
  • 石将从
    2019-09-28
    老师代码能不能写多点注释呀?基础差的同学看得费劲

    作者回复: 好的,我在github上的提交多加一些注释。

    https://github.com/froghui/yolanda

     1
     1
  • HerofH
    2020-01-14
    老师您好!我看到您这在应用层设计了一个读写缓冲区,我之前看了muduo和libevent,也是设计了这样的缓冲区,并且muduo作者陈硕也提到非阻塞IO必须要设计一个应用层Buffer,我很疑惑的就是,这样的读写缓冲区的必要性是什么呢?
    我大概只能理解到非阻塞IO下使用应用层写缓冲区可以让还未来得及发出的数据先保存在应用层Buffer中,然后等到可写的时候再将数据从应用层Buffer写到fd的发送缓冲区中;
    那么如何理解应用层读缓冲区的必要性呢?有数据来,触发可读事件,这个时候直接调用read去读不就可以了吗,为什么一定要先读到读缓冲区呢?根据libevent中,每次读数据时都会尽量多的从fd的接收缓冲区中读取数据到应用层buffer,我的一种想法是,设置读缓冲区的作用,是否是为了减少read的调用次数呢?
    还是有其它原因呢?想了解一下老师的看法,谢谢!
    展开

    作者回复: 读缓冲的作用有很多,你提到了通过设置缓冲区,减少系统调用的次数是一个方面,另外,别忘了读取的数据是需要在应用层进行报文解析的,一个应用层缓冲区显然是比较方便的,否则,需要不断的进行数据的读取,直至解析到完整的报文。我认为,应用层缓冲是"空间换时间"的一个比较好的例子。

    
    
  • skye
    2020-01-09
    read 总是在接收缓冲区有数据时就立即返回,不是等到应用程序给定的数据充满才返回。===
    老师,这个是指阻塞时吗?

    作者回复: 这句话是说,在read调用时,虽然设定需要1k个字节,实际上总是在缓冲区有数据时就立即返回了,有可能只读到了20个字节。这种行为对阻塞和非阻塞是一样的。

    
    
  • javaYJL
    2020-01-07
    老师,客户端发起connect连接。是不是要服务端完成acceptor接入处理,这个tcp连接才算是成功的?

    作者回复: 从系统调用角度来说是的。

    
    
  • 不诉离殇
    2020-01-04
    老师好,我有一个疑问,在使用io复用的情况下,既然内核通知套接口可读,那么这个时候read应该不会阻塞,直接就能返回,那么在io复用情况下,将套接字设置为非阻塞的对read操作有什么意义?非阻塞情况下如果没有数据还需要轮询,消耗cpu,还不如阻塞io?对于readn操作,如果读取的字节数不(假设有一个恶意的客户端,发了一部分数据就不发了),那么阻塞io的read就会一直阻塞(可以加timeout)?非阻塞io会一直轮询?

    作者回复: 非阻塞I/O的好处你已经说到了,就是可以直接返回,不会像阻塞I/O一样一直阻塞。确实,如果是I/O多路复用,看上去阻塞I/O也是可以的,但是它有一个问题,就是容易阻塞,导致线程没耗死。你可以这么简单的理解,本来我们使用非阻塞I/O需要自己不断的轮询,现在操作系统帮我代劳了,可以通过事件来通知我们,这样非阻塞I/O+多路复用就成为了网络编程的一个标准技术了。

    
    
  • 学怪
    2020-01-03
    老师,这个贴出来的代码确定没有问题吗?我自己敲的和GitHub上下载下来的代码都跑不通呢

    作者回复: 你的错误是什么,我确定所有的程序都是可以编译、链接,并最后以可执行程序的方式运行的。

    
    
  • zhang
    2019-12-18
    如果是多线程的,一个线程select(max_fd+1, &read_fds, &write_fds, NULL, NULL),另一个线程想要唤醒第一个线程的select的write_fds,如何做?我试验第二个线程调用第一个线程对象的FD_ZERO(&write_fds);FD_SET(client.sd, &write_fds);,但并没有唤醒select?

    作者回复: 不能这么干。应该是这样,建立一个管道(pipe),然第一个线程同时select这个管道的可读事件,第二个线程往这个管道发送一个字符,这样第一个线程就自然可以苏醒过来了。

     1
    
  • godtrue
    2019-11-24
    非阻塞 I/O 可以被用到读操作、写操作、接收连接操作和发起连接操作上。
    非阻塞是相对于阻塞而言的,阻塞简单讲就是应用程序让内核做某一件事,内核需要点时间做,应用程序在内核做事的这段时间里啥也不干就干等着,直到内核把这件事干完,然后告诉应用程序结果,应用程序才接着干别的事情。
    非阻塞的关键点是,不干等着了,在内核做事的那个时间段内,继续干自己能的事,等内核干完了应用程序交给它干的事,把结果返给应用程序时,应用程序则再继续干拿到结果之后应干的事。
    
    
  • 贺荣伟
    2019-11-21
    这一章需要反复阅读和理解
    
    
  • zmysang
    2019-11-18
    请问老师,我理解select函数是,如果readset中的fd的接收缓冲区不为空,就是可读的,如果writeset中的fd的发送缓冲区没有满就是可写的是吗?

    作者回复: 可以这么理解。当然,接收缓冲去可读的大小,和发送缓冲区可写的大小都是可以通过内核参数动态配置。

    
    
  • javaYJL
    2019-11-05
    老师,accept()这个函数不是阻塞的吗?

    作者回复: accept和阻塞套接字一起使用就是阻塞的,和非阻塞套集字一起使用就是非阻塞的。阻塞和非阻塞是作用到套集字上的。

    
    
  • JasonZhi
    2019-10-17
    第一段代码的注释是否有误?EINTR应该属于中断导致的错误,如:信号中断,如果是非阻塞没有数据可读的情况下,应该返回错误EAGAIN

    作者回复: 你是对的,我已经修正代码,等待编辑更新,感谢指正。

    
    
  • Geek_d4f974
    2019-10-11
    这章真的晦涩难懂啊

    作者回复: 还好吧,这里主要是说非阻塞I/O的含义,以及对我们编写程序的帮助,多读一下,应该可以搞定的。

    
    
  • 传说中的成大大
    2019-10-08
    有连接上来的时候sleep5秒那个例子中 我这边没有永久阻塞 反而是 ./server: accept failed: Invalid argument

    作者回复: 这个例子就是说明一下监听套接字需要设置为非阻塞的,结果不重要了。

    
    
  • 沉淀的梦想
    2019-09-30
    老师代码中进行rot13_char编码的目的是啥?

    作者回复: ROT13(回转13位,rotateby13places,有时中间加了个减号称作ROT-13)是一种简易的置换暗码。

    ROT-13 编码是一种每一个字母被另一个字母代替的方法。这个代替字母是由原来的字母向前移动 13 个字母而得到的。数字和非字母字符保持不变。

    它是一种在网路论坛用作隐藏八卦、妙句、谜题解答以及某些脏话的工具,目的是逃过版主或管理员的匆匆一瞥。ROT13激励了广泛的线上书信撰写与字母游戏,且它常于新闻群组对话中被提及。

    
    
我们在线,来聊聊吧