- 链路层:物理连接
- IP层:路径选择
- TCP/UDP 层: 数据传输
TCP服务器端的默认函数调用顺序
/**
sock: 希望进入连接请求状态的套接字文件描述符
backlog:连接请求等待队列的长度,若为5,表示最多使5个连接请求进入队列
*/
int listen(int sock, int backlog) __DARWIN_ALIAS(listen);
int serv_sock;
listen(serv_sock, 5);
服务器端处于等待连接请求状态是指,客户端请求连接时,受理连接前一直使请求处于等待状态
受理客户端连接请求
/**
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);
TCP客户端
客户端默认函数调用顺序
/**
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的客户端服务端函数调用关系
客户端必须等到服务端调用
listen
后才能调用connect
,同时,客户端调用connect
之前,服务端也可能先调用accept
,但此时会处于阻塞状态,直到客户端调用connect
.
TCP套接字中的I/O缓冲
write
函数调用瞬间,数据将移至输出缓冲,read
函数调用瞬间,从输入缓冲读取数据。
TCP的滑动窗口机制保证不会发生超过输入缓冲大小的数据传输。
TCP三次握手
- A向B传递信息 [SYN] SEQ:1000, ACK:- SEQ1000含义:现在传递的数据包序号为1000,若接收无误,通知我传1001号数据包。 这是首次请求连接时使用的信息,又称SYN,表示收发数据前的同步消息。
- B向A传递消息 [SYN+ACK] SEQ:2000, ACK:1001 SEQ2000含义:现在传递的数据包序号为2000,若无误,通知我传2001号数据包。 ACK1001含义:刚才传递的SEQ1000接收无误,现在请传SEQ1001的数据包。
- A向B传输信息 [ACK] SEQ:1001 ACK:2001 已正确收到传输的SEQ2000数据包,现在可以传输SEQ为2001的数据包了