Learned Points From reading unix network Programming Volumn 1, 记录一下自己学习到的东西。

The listen() interface provided by Unix system

#include <sys/socket.h>
int listen (int sockfd, int backlog); Returns: 0 if OK, -1 on error
  1. For the sencond argument, backlog, it means the maximum queued number matained by the system. Once a connection sent from client, the server received the SYN, that connection will be put into the incomplete connection queue, 接着如果3次连接完成了, 这个connection will be put into the completed connection queue中, which is ready to be returned from the accept() call. 这2个queue的大小不能超过我们在上面接口中设定的backlog的大小。 这个backlog的大小需要根据具体的业务或者应用场景来决定。
    image

close(), shutdown() and SO_LINGER Socket Option

#include <unistd.h> #include <sys/socket.h>
int close (int sockfd); Returns: 0 if OK, -1 on error
int shutdown(intsockfd, inthowto); Returns: 0 if OK, –1 on error
  1. Once you have closed a FD(file descriptor) 并且reference count 减少到0后, 你就不能进行读写了, 默认情况下close 会马上返回。

  2. But for shutdown, 不需要管 reference count,并且可以只shutdown读取的通道或者写的通道。

  3. TCP 的option里面有一个 SO_LINGER的选择, 这个选项用于确定tcp的4次结束的握手是如何进行的.
    struct linger {
    int l_onoff; # // 0 = off, nonzero = on, 是否打开linger
    int l_linger; # // linger time
    }

3.1:If l_onoff is 0, the option is turned off. The value of l_linger is ignored and the previously discussed TCP default applies: close returns immediately
3.2: l_onoff is nonzero and l_linger is zero, TCP aborts the connection when it is closed (pp. 1019–1020 of TCPv2). That is, TCP discards any data still remaining in the socket send buffer and sends an RST to the peer, not the normal four-packet connection termination sequence
3.3: If l_onoff is nonzero and l_linger is nonzero, then the kernel will linger when the socket is closed That is, if there is any data still remaining in the socket send buffer, the process is put to sleep until either: (i) all the data is sent andacknowledged by the peer TCP, or (ii) the linger time expires. If the socket has been setto nonblocking (Chapter 16), it will not wait for the close to complete, even if the linger time is nonzero. When using this feature of the SO_LINGER option, it is important for the
application to check the return value from close, because if the linger time expires before the remaining data is sent and acknowledged, close returns EWOULDBLOCK and any remaining data in the send buffer is discarded.

4.Close function 的默认操作
the image below shows the default operation of close function. 这样子的operation有一个问题就是,因为close是马上返回的, 所以你不知道你发送的数据到底有没有被server给接收到, 可能在你发送data数据之后的某一个时间点, the server or process crashed.
image

5.Close function with SO_LINGER socket option set and l_linger a positive
the image below shows the operation when closing with SO_LINGER socket option set and l_linger a positive
image
这个比之前的那种模式有一个好处就是能知道数据被server正常的读取了(返回了ACK之后才return), 但是还是有问题,因为数据被kernal读了并且返回了ACK并不代表这个数据被application处理了。

6.Using shutdown to know that peer has received our data.
The image below shows the operation of shutdown cliet.
image
当我们使用shutdown with SHUT_WR的时候, 一直等待服务器返回Fin。 说明服务器处理好了我们发送的数据,并且向client发起结束tcp的请求。这样子的操作解决了之前上面的2种问题.

  1. TCP 层内做保证数据已经被读取的通信。
    Client:
    char ack;
    Write(sockfd, data, nbytes);
    n = Read(sockfd, &ack, 1);
    Server:
    nbytes = Read(sockfd, buff, sizeof(buff));
    Write(sockfd, "", 1);
    image
    通过tcp层内的ack承认的方式,这样子的方式也可以保证。但是服务器需要知道到底要读多少数据后才发送ack。可以通过应用的特点来设置。比如说,最简单的一个服务发送一个320640的没有压缩的图片, 这样子的话服务器只需要读到(320640*3)个字节后就可以发送一个ack标志。

socket的缓存设置, SO_RCVBUF and SO_SNDBUF Socket Options。

在设置缓存的时候,有一点很重要。就是 bandwidth-delay product = bandwidth * RTT(in seconds)。因为 服务器会保存所有的数据,直到收到ACK的包才会丢弃数据,释放缓存。所以在设置SO_SNDBUF的时候一定要大于你的bandwidth-delay product。比如说你的音频服务器发送一首歌的数据,平均的码流是1.41Mbit/sec。 你的RTT通过ping来计算是100ms. 那你的SO_SNDBUF 至少得大于 1.41Mbit/sec * 100ms = 17625byte

Reference:

unix network Programming Volumn 1

posted @ 2021-08-26 18:05  哇哩顾得  阅读(74)  评论(0编辑  收藏  举报