目录
1.昨天套接字服务器的弊端
```shell
# fast sender -> 客户端
# slow recevicer -> 服务器端
# mss(Maximum Segment Size,单条数据最大长度)
# SYN: 请求建立连接
# ACK: OK
# FIN: 请求断开连接
# win: 滑动窗口大小
############################### 三次握手 ###############################
第1步:
客户端:
1. 给服务器发送建立连接的请求 tcp协议中的 SYN 赋值为1
2. 0(0):
1). 第一个0: 客户端生成的随机序号
2). 第二个0: 客户端给服务器发送数据携带的数据量
3. win4096: 客户端能够缓存的最大数据量为 4k
4. mss 1460: 可处理的单条最大字节数1460
第2步:
服务器:
1. ACK, 客户端同意的客户端的连接请求
2. 1 代表确认序号, 客户端生成的随机序号 + 接收的数据量
- 0 + 1 = 1
3. SYN: 服务器请求和客户端建立连接
4. 8000(0)
- 8000: 服务器端生成的随机序号
- 0: 服务器给客户端发送数据携带的数据量
5. win 6144: 服务器端能够缓存的最大数据量为6k
6. mss 1024: 服务器端处理的单条数据最大长度 1k
第3步:
客户端:
1. ACK: 同意了服务器的连接请求
2. 8001: 确认序号 = 服务器生成的随机序号 + 服务器给客户端发送的字节数
8000 + 1 = 8001
3. win 4096: 现在客户端可以缓存的最大数据量是4k
############################### 数据通信 ###############################
2.如何通过多进程方式实现服务器并发
第4步:
客户端给服务器发送数据:
1. 1(1024)
1). 上一次的确认序号, 服务器回复给客户端
- 1代表次已经成功发送了1个字节, 这次发送的数据量是1024字节
2. 8001: 确认序号 = 服务器生成的随机序号 + 服务器给客户端发送的字节数
8000 + 1 = 8001
3. win 4096: 现在客户端可以缓存的最大数据量是4k
第5,6,7,8,9 略, 参考第4步
到第9步, 服务器接收数据的缓存被写满, 客户端的发送被阻塞了
第10步:
1. ack 6145: 确认序号, 客户端发送给服务器的6145字节已经收到了
接收的实际字节数: 确认序号 - 生成的随机序号
2. win 2048: 告诉客户端服务器的接收数据的缓存大小为2k
- 因为有2k数据被服务器端处理掉了
第11步:
1. ack 6145: 确认序号, 客户端发送给服务器的6145字节已经收到了
接收的实际字节数: 确认序号 - 生成的随机序号
2. win 4096: 告诉客户端服务器的接收数据的缓存大小为4k
- 因为有4k数据被服务器端处理掉了
3.多进程服务器-1
```c
// 主线程 -> 等待并接受客户端的连接
// 子线程 -> 建立连接之后处理通信的流程
// 多个线程共用同一个虚拟地址空间
共享资源:
- 堆区
- 全局数据区
- 文件描述符表
独享资源:
- 栈区
// 线程资源释放: 做线程分离
```
```c
void* callback(void* arg)
{
// 子线程的处理动作
while(1)
{
// 通信
int len = recv();
if(len == 0)
{
break;
}
send();
}
}
int main()
{
int lfd = socket();
bind();
listen();
while(1)
{
int cfd = accept();
// 创建子线程
pthread_create(&tid, NULL, callback, arg);
}
}
```
4.多进程服务器-2
IP:
- 种类:
- 局域网
- 192.168.xx.xx
- 广域网(公网)
- 88.99.1.34
- 协议(网络层)
- ipv4
- 4字节整数, 一般使用点分十进制字符串表示
- ipv6
- 16字节, 分成八份, 每份两个字节
- 作用:
- 主机的家, 主机的地址, 通过ip就能找到网络中的某台主机
- 端口
- unsigned short
- 作用: 定位主机上的一个进程
- 只有需要网络通信的进程才需要绑定端口
- 取值范围 0-65535
- 使用, 通过浏览器进行服务器访问:
- 192.168.1.100:9999
- 域名:
- 特殊的字符串, 需要和IP绑定, 成功之后才可以访问服务器
- 域名访问-> 域名解析 -> 得到IP -> 通过IP访问服务器
- 字节序:
- 数据在内存中的存储顺序, 单位是字节
- 字符串没有字节序问题
- 分类:
- 大端(网络字节序)
- 高低, 低高
- 网络通信的时候用大端
- IP和端口
- 传输的数据 (如果是字符串就可以不转换了)
- 小端(主机字节序) 0x12345678
- 低低, 高高
- 我们使用的pc机默认是小端存储
5.多进程版程序-回收子进程被信号中断的处理
基于tcp的通信流程
- 服务器
1. 创建监听的套接字
int lfd = socket();
2. 和本地的IP port绑定
bind();
3. 设置监听
listen()
4. 阻塞等待客户端连接
int cfd = accept();
6.多线程版TCP服务处理思路
4. 阻塞等待客户端连接
int cfd = accept();
5. 通信
read/recv
write/send
6. 关闭文件描述符
close()
- 客户端
1. 创建通信的套接字
int cfd =socket();
2. 连接服务器, 通过服务器绑定的地址, 地址信息需要使用网络字节序
connect();
3. 通信
read/recv
write/send
4. 关闭文件描述符
close();
7.多线程并发服务器编写
8.为什么不能把文件描述符地址传到子线程中