《TCP/IP网络编程》第5章 基于TCP的服务器端/客户端(2)

5.1 回声客户端的完美实现

1.       回声服务器端没有问题,只有客户端有问题。

    回声客户端传输的是字符串,而且是通过调用write函数一次性发送的,之后还调用一次read函数,期待着接收自己传输的字符串。

2.       回声客户端问题解决方法

    解决:因为可以提前确定接收数据的大小,若之前传输了20字节长的字符串,则在接收时循环调用read函数读取20个字节即可。

3.       如果问题不在于回声客户端:定义应用层协议

    由于回声客户端已知需要接收数据的长度,所以问题容易解决,但是如果无法提前预知需要接收数据长度,该如何?此时需要应用层协议的定义。

    服务器端/客户端实现过程中逐步定义的这些规则几何就是应用层协议。可以看出,应用层协议并不是高深莫测的存在,只不过是为特定程序的实现而制定的规则。

4.       实现计算器服务器端/客户端示例(设计应用层协议)

    操作如下所示:

《TCP/IP网络编程》第5章 基于TCP的服务器端/客户端(2)

    编写程序前,设计如下应用层协议:

  • 客户端连接到服务器端之后以1字节整数形式传递待算数字个数;
  • 客户端向服务器端传递的每个整数型数据占用4字节;
  • 传递整数型数据后接着传递运算符。运算符信息占用1字节;
  • 选择字符+、-、*之一传递;
  • 服务器端以4字节整数型向客户端传回运算结果;
  • 客户端得到运算结果后终止与服务器端的连接;

    若想在同一数组中保存并传输多种数据类型,应把数组声明为char类型,而且需要额外做一些指针及数组运算。

5.2 TCP原理

1.       TCP套接字中的I/O缓冲

    服务器端即使调用1次write函数传输40字节的数据,客户端也有可能通过4次read函数调用每次读取10字节。

    实际上,write函数调用后并非立即传输数据,read函数调用后也并非马上接收数据。

《TCP/IP网络编程》第5章 基于TCP的服务器端/客户端(2)

    这些I/O缓冲特性如下:

  • I/O缓冲在每个套接字中单独存在;
  • I/O缓冲在创建套接字时自动生成;
  • 即使关闭套接字也会继续传递输出缓冲中遗留的数据;
  • 关闭套接字将丢失输入缓冲的数据;

    TCP会控制数据流,TCP中有滑动窗口协议(SlidingWindow)协议。

    write函数和Windows的send函数并不会在完成向对方主机的数据传输时返回,而是在数据移到输出缓冲时。但TCP会保证对输出缓冲数据的传输,所以write函数在数据传输完成时返回。

2.       TCP内部工作原理1:与对方套接字的连接

    Three-way handshaking(三次握手):

《TCP/IP网络编程》第5章 基于TCP的服务器端/客户端(2)

3.       TCP内部工作原理2:与对方主机的数据交换

《TCP/IP网络编程》第5章 基于TCP的服务器端/客户端(2)

    ACK号—> SEQ号 + 传递的字节数 + 1 ,告知对方下次要传递的SEQ号。

4.       TCP的内部工作原理3:断开与套接字的连接

双方断开连接的过程又称四次握手(Four-wayhandshaking)。

《TCP/IP网络编程》第5章 基于TCP的服务器端/客户端(2)