diff --git a/ch06/README.md b/ch06/README.md index 37ae639..7ed73bd 100644 --- a/ch06/README.md +++ b/ch06/README.md @@ -8,7 +8,7 @@ TCP 是内容较多的一个协议,而本章中的 UDP 内容较少,但是 #### 6.1.1 UDP 套接字的特点 -通过寄信来说明 UDP 的工作原理,这是讲解 UDP 时使用的传统示例,它与 UDP 的特点完全相同。寄信前应现在信封上填好寄信人和收信人的地址,之后贴上邮票放进邮筒即可。当然,信件的特点使我们无法确认信件是否被收到。邮寄过程中也可能发生信件丢失的情况。也就是说,信件是一种不可靠的传输方式,UDP 也是一种不可靠的数据传输方式。 +通过寄信来说明 UDP 的工作原理,这是讲解 UDP 时使用的传统示例,它与 UDP 的特点完全相同。寄信前应先在信封上填好寄信人和收信人的地址,之后贴上邮票放进邮筒即可。当然,信件的特点使我们无法确认信件是否被收到。邮寄过程中也可能发生信件丢失的情况。也就是说,信件是一种不可靠的传输方式,UDP 也是一种不可靠的数据传输方式。 因为 UDP 没有 TCP 那么复杂,所以编程难度比较小,性能也比 TCP 高。在更重视性能的情况下可以选择 UDP 的传输方式。 @@ -26,7 +26,7 @@ TCP 与 UDP 的区别很大一部分来源于流控制。也就是说 TCP 的生 UDP 也具有一定的可靠性。对于通过网络实时传递的视频或者音频时情况有所不同。对于多媒体数据而言,丢失一部分数据也没有太大问题,这只是会暂时引起画面抖动,或者出现细微的杂音。但是要提供实时服务,速度就成为了一个很重要的因素。因此流控制就显得有一点多余,这时就要考虑使用 UDP 。TCP 比 UDP 慢的原因主要有以下两点: -- 收发数据前后进行的连接设置及清楚过程。 +- 收发数据前后进行的连接设置及清除过程。 - 收发过程中为保证可靠性而添加的流控制。 如果收发的数据量小但是需要频繁连接时,UDP 比 TCP 更高效。 @@ -39,7 +39,7 @@ UDP 中的服务端和客户端不像 TCP 那样在连接状态下交换数据 #### 6.2.2 UDP 服务器和客户端均只需一个套接字 -TCP 中,套接字之间应该是一对一的关系。若要向 10 个客户端提供服务,除了守门的服务器套接字之外,还需要 10 个服务器套接字。但在 UDP 中,不管事服务器端还是客户端都只需要 1 个套接字。只需要一个 UDP 套接字就可以向任意主机传输数据,如图所示: +TCP 中,套接字之间应该是一对一的关系。若要向 10 个客户端提供服务,除了守门的服务器套接字之外,还需要 10 个服务器套接字。但在 UDP 中,不管是服务器端还是客户端都只需要 1 个套接字。只需要一个 UDP 套接字就可以向任意主机传输数据,如图所示: ![](https://i.loli.net/2019/01/17/5c3fd703f3c40.png) @@ -54,7 +54,7 @@ TCP 中,套接字之间应该是一对一的关系。若要向 10 个客户端 ssize_t sendto(int sock, void *buff, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen); /* -成功时返回传输的字节数,失败是返回 -1 +成功时返回发送的字节数,失败时返回 -1 sock: 用于传输数据的 UDP 套接字 buff: 保存待传输数据的缓冲地址值 nbytes: 待传输的数据长度,以字节为单位 @@ -71,7 +71,7 @@ addrlen: 传递给参数 to 的地址值结构体变量长度 ssize_t recvfrom(int sock, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen); /* -成功时返回传输的字节数,失败是返回 -1 +成功时返回接收的字节数,失败时返回 -1 sock: 用于传输数据的 UDP 套接字 buff: 保存待传输数据的缓冲地址值 nbytes: 待传输的数据长度,以字节为单位 @@ -109,7 +109,7 @@ TCP 客户端套接字在调用 connect 函数时自动分配IP地址和端口 #### 6.2.5 UDP 客户端套接字的地址分配 -仔细观察 UDP 客户端可以发现,UDP 客户端缺少了把IP和端口分配给套接字的过程。TCP 客户端调用 connect 函数自动完成此过程,而 UDP 中连接能承担相同功能的函数调用语句都没有。究竟在什么时候分配IP和端口号呢? +仔细观察 UDP 客户端可以发现,UDP 客户端缺少了把IP和端口分配给套接字的过程。TCP 客户端调用 connect 函数自动完成此过程,而 UDP 中连能承担相同功能的函数调用语句都没有。究竟在什么时候分配IP和端口号呢? UDP 程序中,调用 sendto 函数传输数据前应该完成对套接字的地址分配工作,因此调用 bind 函数。当然,bind 函数在 TCP 程序中出现过,但 bind 函数不区分 TCP 和 UDP,也就是说,在 UDP 程序中同样可以调用。另外,如果调用 sendto 函数尚未分配地址信息,则在首次调用 sendto 函数时给相应套接字自动分配 IP 和端口。而且此时分配的地址一直保留到程序结束为止,因此也可以用来和其他 UDP 套接字进行数据交换。当然,IP 用主机IP,端口号用未选用的任意端口号。 @@ -121,7 +121,7 @@ UDP 程序中,调用 sendto 函数传输数据前应该完成对套接字的 前面说得 TCP 数据传输中不存在数据边界,这表示「数据传输过程中调用 I/O 函数的次数不具有任何意义」 -相反,UDP 是具有数据边界的下一,传输中调用 I/O 函数的次数非常重要。因此,输入函数的调用次数和输出函数的调用次数完全一致,这样才能保证接收全部已经发送的数据。例如,调用 3 次输出函数发送的数据必须通过调用 3 次输入函数才能接收完。通过一个例子来进行验证: +相反,UDP 是具有数据边界的下一,传输中调用 I/O 函数的次数非常重要。因此,输入函数的调用次数和输出函数的调用次数应该完全一致,这样才能保证接收全部已经发送的数据。例如,调用 3 次输出函数发送的数据必须通过调用 3 次输入函数才能接收完。通过一个例子来进行验证: - [bound_host1.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch06/bound_host1.c) - [bound_host2.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch06/bound_host2.c) diff --git a/ch07/README.md b/ch07/README.md index dba1722..1b77687 100644 --- a/ch07/README.md +++ b/ch07/README.md @@ -48,7 +48,7 @@ howto: 传递断开方式信息 - `SHUT_WR` : 断开输出流 - `SHUT_RDWR` : 同时断开 I/O 流 -若向 shutdown 的第二个参数传递`SHUT_RD`,则断开输入流,套接字无法接收数据。即使输入缓冲收到数据也回抹去,而且无法调用相关函数。如果向 shutdown 的第二个参数传递`SHUT_WR`,则中断输出流,也就无法传输数据。若如果输出缓冲中还有未传输的数据,则将传递给目标主机。最后,若传递关键字`SHUT_RDWR`,则同时中断 I/O 流。这相当于分 2 次调用 shutdown ,其中一次以`SHUT_RD`为参数,另一次以`SHUT_WR`为参数。 +若向 shutdown 的第二个参数传递`SHUT_RD`,则断开输入流,套接字无法接收数据。即使输入缓冲收到数据也会抹去,而且无法调用相关函数。如果向 shutdown 的第二个参数传递`SHUT_WR`,则中断输出流,也就无法传输数据。若如果输出缓冲中还有未传输的数据,则将传递给目标主机。最后,若传递关键字`SHUT_RDWR`,则同时中断 I/O 流。这相当于分 2 次调用 shutdown ,其中一次以`SHUT_RD`为参数,另一次以`SHUT_WR`为参数。 #### 7.1.4 为何要半关闭