• 破晓^_^
    2019-08-12
    无限增大缓冲区肯定不行,文章中已经说过write函数发送数据只是将数据发送到内核缓冲区,而什么时候发送由内核觉定。内核缓冲区总是充满数据时会产生粘包问题,同时网络的传输大小MTU也会限制每次发送的大小,最后由于数据堵塞需要消耗大量内存资源,资源使用效率不高。
    用户缓冲区到内核缓冲区
    内核缓冲区IP报文,一次三拷贝,总共6次。不知对否?

    作者回复: 都是强人😄

     11
     31
  • fjpcode
    2019-08-13
    1. 缓冲区搞大一些,在一定程度上能够减少write/send等系统调用,减少用户空间和内核空间的切换。但是和吞吐量并没有直接关系,
    还可能导致数据都挤压到内核缓冲区得不到处理,造成内存消耗的问题。
    2. 发送方:用户空间-->内核缓冲区-->报文封装 三次拷贝,接收方反向过来,所以应该是6次。
     4
     12
  •  
    2019-08-13
    尝试着照着老师贴出来的代码写了一个,可以跑起来
    https://github.com/yingcheng-zhou/socket-reading-and-writing

    作者回复: 👍

     4
     11
  • Geek_Wison
    2019-08-12
    老师可以将完整的代码的github地址贴出来吗,我想自己编译调试运行一下。

    作者回复: 正在进行中

     4
     5
  • Geek_362669
    2019-09-03
    关于write函数的返回值那里还是不太懂,当它的返回值(数值大小)小于期望写入的字节数,那它的值代表什么呢???

    作者回复: 表示缓冲区就那么大,装不下你要的那么大的字节流,就返回了目前能装下的部分,剩下的部分应用程序要自己接着往里装。

    
     3
  • Sweety
    2019-08-12
    对C不了解,有点不好理解.
    只能将就的看懂方法.
    第一次认真跟课,就给自己挖了一个坑.
    理解思想吧

    作者回复: 答疑篇会稍微点拨一下C语言

    
     3
  • 学怪
    2019-12-06
    网络编程中为什么要循环读取数据呢?

    作者回复: 因为数据像流水一样,不会结束,所以叫做stream流。

    
     2
  • 禾桃
    2019-08-16
    13-14 行表示的是非阻塞 I/O 的情况下,没有数据可以读,需要继续调用 read。

    EINTR The call was interrupted by a signal before any data was read;
                  see signal(7).

    貌似这个场景是因为read这个函数在执行过程中被一个信号中断,而没有执行完提前退出了,

    您的意思是只有在socket被设置为非阻塞的前提下,才会出现?

    如果socket之前被设成阻塞,read就不会返回,直到这个信号被处理了,如果处理后返回这个进程,读取的操作会继续进行下去,直到read函数返回?

    多谢!
    展开

    作者回复: 阻塞那部分确实是这样的,当然,可以为read设置超时。

     2
     2
  • 传说中的成大大
    2019-08-13
    还有就是通过现象说明 应用程缓冲区虽然是10240000但是套接字缓冲区应该不是10240000这么大它一次性没写完,这也是为啥服务器端在不停的打印收到的字节数 这说明在客户端send未完全拷贝到套接字缓冲区之前他是不会返回的
    
     2
  • 业余爱好者
    2019-08-12
    网络程序的性能瓶颈一般在于服务端,所以老师说的增加缓冲区大小应该指的是服务端。如果应用程序的处理速度跟不上,即使缓冲区再大,也不能在整体上提高太多的吞吐率。性能,从来都只能从整体上优化,简单粗暴地提升某一个指标的效果一般。

    首先讲客户端发送的数据拷贝到缓冲区,
    然后操作系统讲数据从客户端的缓冲区中发往服务端的缓冲区。服务端操作系统最后把数据从缓冲区搬移到应用程序。客户端应用--客户端缓冲区--服务端缓冲区--服务端应用程序。一共3次?
     1
     2
  • 麻雀
    2020-01-09
    #include "config.h" 我引入的common.h也找不到这个头文件

    作者回复: 这需要通过cmake自动产生。

    根目录下CMakeLists.txt有这么一段:

    # check epoll and add config.h for the macro compilation
    include(CheckSymbolExists)
    check_symbol_exists(epoll_create "sys/epoll.h" EPOLL_EXISTS)
    if (EPOLL_EXISTS)
        # Linux下设置为epoll
        set(EPOLL_ENABLE 1 CACHE INTERNAL "enable epoll")

        # Linux下也设置为poll
    # set(EPOLL_ENABLE "" CACHE INTERNAL "not enable epoll")
    else ()
        set(EPOLL_ENABLE "" CACHE INTERNAL "not enable epoll")
    endif ()

     1
     1
  • 旅途
    2019-12-29
    老师 问一下 send into buffer 这句话 看代码里 应该是每次 发送完都会打印出来 为什么调小发送字节数后才能打出来呢?

    作者回复: 如果你问的是第二个实验的结果,其实是这样的,确实每次发送都会打印出"send into buffer"这句话,问题是这里的程序一次性的将query字符串发送到了发送缓冲区,而发生缓冲区如果足够大,那么是可以一次性的容纳这部分数据的,所以当我们把发送字节数从从 10240000 调整为 1024000,就会直接看到"send into buffer"这句话

    
     1
  • 衬衫的价格是19美元
    2019-10-01
    就像老师说的仓库的例子,在write的时候,如果缓冲区设定的很大,那么应用程序每次往缓冲区写数据的时候,都会返回完整的数据大小,应用程序以为数据发送没问题,于是接着往缓冲区写,但实际呢?可能由于网络的原因,实际数据发送的很慢,数据都堆积在缓冲区,并没有发出去,但是在达到缓冲区上限之前,应用程序都是无法感知的,而一旦感知到的时候,发现已经有山一样的数据堆积在缓冲区了

    作者回复: 应该是网卡或者网络原因。

     1
     1
  • Kepler
    2019-09-18
    没有答案吗,数据从应用程序发送端,到应用程序接收端到底为啥是6次?

    作者回复: 在答疑篇中有一个我认为的答案,其实这是一个开放性问题,不用纠结这个数据,主要是明白拷贝发生的场景,为什么为发生拷贝。

    
     1
  • 传说中的成大大
    2019-08-13
    我通过百度把示例代码跑起来了 当客户端连接成功服务器过后 开始发送数据 服务器的终端不停打印,然后我发现一个现象就是 因为打印太多 能看到的是 9723 每一秒涨1 第二秒就是 9724 9725 9726等一直到1000我想问的是为什么一秒比一秒多1呢?当服务器端打印完过后客户端打印 send into buffer 10240000然后程序退出
     2
     1
  • 徐凯
    2019-08-12
    我想问一下 用户态缓存是否指的是运行库的缓存 我的意思就是 write最终是要调用系统调用的 而我们使用的是运行库的write函数 为了避免像发一个字节就立马调用系统调用 运行库也会有缓存来尽量减少系统调用的次数 这个是不是就是指的是用户态缓存 而不是指用户在程序中自己定义的一段buffer数组对吧

    作者回复: 我理解不是这样的,咱们调用write就是一个系统调用,就会有用户态-内核态的上下文切换,你说的这个问题,确实是实战中应该尽量避免的,我在后面的提高篇中会针对你说的这个情况讲到一些技巧。

    
     1
  • 范龙dragon
    2019-08-12
    第一个readn函数中第24行返回实际字节数的地方,应该是size-nleft吧,通篇没有看到变量n

    作者回复: 已经修复

     1
     1
  • 天蝎座的狮子狗
    2019-08-12
    我遇到一个问题,发送函数send函数返回值竟然比我写的时候传入的buff的bufflen大,不知道为什么😳。

    作者回复: 出错了.... 代码贴出来看看

    
     1
  • 在路上
    2019-08-12
    个人的想法:
    单纯的提高缓冲区应该不是可行的方法,以一台计算机思考,内存毕竟是有限的,为每个套接字都开辟一大块内存,那相应可以创建的套接字的就减少了把

    作者回复: 相当于让仓库变大,可以存储了更多的货物,如果出货的速度有限,会有更多的货物烂在仓库里。

    
     1
  • 星亦辰
    2019-08-12
    有这么一个问题:

    假如客户端往服务端发送了1025个字节,而只有1024个字节是有用的。
    我在服务端用read 读取1024个字节,最后一定是返回1024。
    然后,剩下的没有用了,不打算读了,怎么样抛弃多余的内容呢。

    作者回复: 那你为啥要传这第1025个字节呢?如果是消息的边界,例如换行,还是要读到这个字符的,读完以后不拷贝到应用程序的缓冲区就可以认为是丢弃了。

     2
     1
我们在线,来聊聊吧