网络编程:基于TCP的服务器端

38 阅读3分钟

image (1).png

  • 链路层:物理连接
  • IP层:路径选择
  • TCP/UDP 层: 数据传输

TCP服务器端的默认函数调用顺序

image.png

/**
  sock: 希望进入连接请求状态的套接字文件描述符
  backlog:连接请求等待队列的长度,若为5,表示最多使5个连接请求进入队列
*/
int listen(int sock, int backlog) __DARWIN_ALIAS(listen);

int serv_sock;
listen(serv_sock, 5);

服务器端处于等待连接请求状态是指,客户端请求连接时,受理连接前一直使请求处于等待状态

image (2).png

受理客户端连接请求

/**
  sock: 服务器端套接字的文件描述符
  addr: 保存发起连接请求的客户端地址信息的变量地址值,调用函数后向传递来的地址变量参数填充客户端地址信息
  addrlen: 第二个参数addr结构体的长度,但是存有长度的变量地址。
*/
int accept(int sock, struct sockaddr * addr, socklen_t * addrlen);

struct sockaddr_in clnt_addr;
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

image.png

TCP客户端

客户端默认函数调用顺序

image (1).png

/**
  sock: 客户端套接字文件描述符
  servaddr: 保存目标服务器端地址信息的变量地址值
  addrlen: 以字节为单位已传递给第二个结构体参数servaddr的地址变量长度
*/
int connect(int sock, struct sockaddr * servaddr, socklen_t addrlen);

connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

调用connect后,以下情况会返回

  • 服务器端接收连接请求
  • 发生断网等异常情况中断连接 所谓接收连接不意味着server端调用accept函数,只是将连接请求信息记录到等待队列,因此connect后并不立即进行数据交换。

问:客户端的IP地址和端口如何分配的? 何时?调用 connect函数时 何地?操作系统,更准确说是内核中 如何?IP用计算机的IP,端口随机

基于TCP/IP的客户端服务端函数调用关系

image (2).png 客户端必须等到服务端调用listen后才能调用connect,同时,客户端调用connect之前,服务端也可能先调用accept,但此时会处于阻塞状态,直到客户端调用connect.

TCP套接字中的I/O缓冲

write函数调用瞬间,数据将移至输出缓冲,read函数调用瞬间,从输入缓冲读取数据。

image.png TCP的滑动窗口机制保证不会发生超过输入缓冲大小的数据传输。

TCP三次握手

image (1).png

  1. A向B传递信息 [SYN] SEQ:1000, ACK:- SEQ1000含义:现在传递的数据包序号为1000,若接收无误,通知我传1001号数据包。 这是首次请求连接时使用的信息,又称SYN,表示收发数据前的同步消息。
  2. B向A传递消息 [SYN+ACK] SEQ:2000, ACK:1001 SEQ2000含义:现在传递的数据包序号为2000,若无误,通知我传2001号数据包。 ACK1001含义:刚才传递的SEQ1000接收无误,现在请传SEQ1001的数据包。
  3. A向B传输信息 [ACK] SEQ:1001 ACK:2001 已正确收到传输的SEQ2000数据包,现在可以传输SEQ为2001的数据包了

TCP四次挥手

image (2).png