TCPIP 网络编程-04-基于TCP的CS

有了地址的设置函数之后,接下来就是开始进行连接

服务端存在两个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/socket.h>

/**
* 通过调用 listen 函数进入等待连接请求状态。(只有调用 listen,客户端才能发起 connect)
* sock 希望进入等待连接请求的状态的套接字文件描述
* backlog 连接请求等待队列(Queue)的长度,若位 5,表示最多使5个连接请求进入队列
*/
int listen(int sock, int backlog);

/**
* 受理客户端连接请求,返回一个套接字连接到发起请求的客户端
* sock 服务端套接字的文件描述符
* addr 保存发起连接请求的客户端地址信息的变量地址值
* addrlen 第二个参数 addr 结构体的长度
* 成功返回创建的套接字文件描述符,失败返回-1
*/
int accept(int sock, struct sockaddr * addr, socklen_t * addr_len);

accept 函数受理连接请求等待队列中待处理的客户端连接请求

客户端使用 connect发起连接请求

1
2
3
4
5
6
7
/**
* 向服务端发起请求连接
* sock 客户端套接字文件描述符
* servaddr 保存目标服务端地址信息的变量地址值
* addrlen 第二个参数结构体的长度
*/
int connect(int sock, struct sockaddr * server_addr, socklen_t addr_len);

客户端调用 connect 之后,可能发生以下情况之一才返回(完成函数调用)

  1. 服务端接收连接请求

  2. 发生断网导致一场情况而中断连接请求(阻塞的)

客户端connect的时候并没有指定客户端的地址,那么是什么时候分配的ip 与端口?其实是自动分配的,所以客户端无需调用标记的 bind 函数进行分配

TIPS: 接收连接并不意味着服务端调用 accept 函数,而是服务端把连接请求信息记录到等待队列。因此 connect 函数返回之后并不立即进行数据交换,那么问题来了,客户端既然不知道服务端是否已经 accept 了,那么如果客户端立即 write 发送数据,数据到服务端会是一个什么状态

答:如果服务器端尚未调用 accept,连接处于已建立但未接受的状态。在这种情况下,发送的数据将保留在等待队列中,等待服务器端调用 accept 来接受连接。一旦服务器端调用了 accept,则可以开始在客户端和服务器端之间进行数据交换

所以函数的调用关系如下

Snipaste_2024-01-02_21-49-18

这章要求是写一个回写 CS,代码:https://github.com/XBoom/network-ip.git 中的 apps/socket/06/执行结果,服务端接收到消息之后恢复给客户端,有两种情况,每一次写入都原样写回;第二种是每次的写入收集起来一次写回

要求:

  1. 服务器端在同一时刻只能与一个客户端相连,并提供回声服务
  2. 服务器端一次向5个客户端提供服务并退出
  3. 客户端接收用户输入的字符串并发送到服务器端
  4. 服务器端将接收的字符串数据传回客户端,即“回声服务”
  5. 服务器端与客户端之间的字符串回声一致执行到客户端输入Q
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root]#./server 5555
[06/server.c:44 main info] accept socket 4
[06/server.c:49 main info] recv message:client1
[06/server.c:55 main info] reponse len 7 message:client1
[06/server.c:44 main info] accept socket 4
[06/server.c:49 main info] recv message:client2
[06/server.c:55 main info] reponse len 7 message:client2
[06/server.c:44 main info] accept socket 4
[06/server.c:49 main info] recv message:client3
[06/server.c:55 main info] reponse len 7 message:client3
[06/server.c:44 main info] accept socket 4
[06/server.c:49 main info] recv message:client4
[06/server.c:55 main info] reponse len 7 message:client4
[06/server.c:44 main info] accept socket 4
[06/server.c:49 main info] recv message:client5
[06/server.c:55 main info] reponse len 7 message:client5
[06/server.c:60 main info] reponse message end

读写操作 read/write 由于是无边界,数据存储在IO缓存区等待读写

image-20240105204229710

IO缓存区有以下特点

  • IO缓冲在每个TCP套接字中单独存在
  • IO缓冲在创建套接字时自动生成
  • 关闭套接字会继续传递输出缓冲中遗留的数据
  • 关闭套接字会丢失输入缓冲中的数据

TIPS: 输出不丢失是因为系统自动进行发送操作,而输入丢失是因为套接字关闭了输入缓冲中的数据也没有人能够读到了,也就丢掉

参考文档

  1. 《TCPIP 网络编程》