一、TCP客户端
-
客户端通过connect()来完成3次握手,服务器通过accept()来完成3次握手
-
WireShark抓包三次握手的结果——
抓包三次握手
1.1 如果服务器关闭,客户端依然发起连接会是什么情况?
注意RST客户端依然会发送一个SYN报文,但是服务器会返回一个RST和ACK,ACK是应答SYN,RST则表示
需要重置
。
- 如果把网线拔了,那么就会造成网络不通畅,那么
什么都发不过去
。
1.2 服务器端代码的改变
-
为了可以进行读写数据,对代码进行改写——
图示代码
服务器端
读完一遍马上就会关闭
1.3 客户端代码
原先的TCP客户端
改写的TCP客户端
1.4 使用wireshark观察协议栈的变化
注意:`PSH`标志位
- 这时候就会有
应用层的数据helloworld
了
1.5 read()函数是否是阻塞的?
- 如果没有数据可读取,read()函数默认是
阻塞
的。
read是阻塞的
我们可以在write()之前先sleep()个10s,发现服务器那里就在一直等着,10s后会读取到write()中包含的数据
- 如何将阻塞的改成非阻塞的呢?——使用
fcntl()系统调用
1.6 write()函数调用2次,但服务器读的时候只读一次
- 写端进行写2次,写2串数据,服务器端只读1次的情景——
客户端代码:
图示代码
服务器端代码还是跟之前一样,不要改变
- 结果是write()函数调用2次发送的
2个字符串
,都一次性
读完了
结果
原因是TCP是一个
流协议
,而不是一个数据报协议
。数据报也许是一整块一整块的,但是流协议就像管道一样,会排队,有先后之分。
二、服务器循环读取数据
- 之前的服务器都是
只读一次
,现在改成循环读取数据——
加一个循环,并且不关闭文件描述符fd
循环读取客户端发送来的数据代码
2.1 优化后的服务器代码
- 之前的代码有Bug,如果客户端关闭了连接。接收到的字符数量就是0,那么就需要直接关闭fd,而不是继续读取——
这里的代码没有加break
加上break
2.2 如果是多个客户端会不会有问题
- 不会出现客户端端口被占用的问题
因为客户端的端口都是临时分配的,不会产生
端口被占用
的情况
- 但是会出现,客户端A发生数据可以被服务器接收,但是客户端B发送数据接受不了,只有当客户端A关闭后,服务器才会接收到客户端B发送来的数据
三、客户端循环发送数据
图示代码
网友评论