本节学习内容
1.主机字节序列和网络端字节序列
2.套接字地址结构(1.通用套接字2.专用套接字3.ip地址转换函数)
3.网络编程常用接口
4.TCP编程流程(多进程、多线程处理)
5.TCP(1.TCP协议特点2.TCP协议服务器端与客户端传输流程3.三次握手四次挥手4.流式服务特点(粘包问题)5.TCP的连接状态(TINME_WAIT状态存在的意义))
一、主机字节序列和网络端字节序列
1.数据存储方式
(1)大端存储方式:高位字节存储在低地址,低位字节存储在高地址
(2)小端存储方式:低位字节存储在低地址,高位字节存储在高地址
2.主机字节序列:不同主机采用的字节序列可能不同,分为大端字节序列和小端字节序列
3.网络字节序列:大端字节序列
二、套接字(socket)地址结构 头:sys/socket.h
1.通用套接字(socketaddr)地址结构
socket网络编程中表示socket地址的是结构体sockaddr(通用套接字)
struct sockaddr
{
sa_family_t sa_family;
char as_data[14];
}
2.专用套接字地址结构
(1)TCP/IP协议族中sockaddr_in用于IPV4地址格式,sockaddr_in6用于IPV6地址格式
(2)IPV6地址结构体如下
struct in _ addr
{
u_int32_t s_ addr;
};
struct sockaddr _ in
{
sa _ family _t sin _ family; //地址族:AF_INET(ipv4地址族)
u_int16_t sin _ port; //端口号(大于4096为临时端口号)
struct in _ addr.sin _ addr; //服务器端ip地址
};
(3)IPV6地址结构体如下
struct in6_ addr
{
unsigned char sa _ addr[16]; // IPV6地址, 要用网络字节序表示
};
struct sockaddr _in6
{
sa _ family _t sin6_ family; // 地址族: AF_INET6
u_inet16_t sin6_ port; // 端口号: 用网络字节序表示
u_int32_t sin6_ flowinfo;// 流信息, 应设置为0
struct in6_ add r sin6_ addr; // IPV6地址结构体
u_int32_t sin6_ scope _ id; // scope ID, 尚处于试验阶段
};
3.ip地址转换函数 头:arpa/inet.h
一般情况下,用点分十进制字符串表示IPV4地址,但编程需要转化为整数才能使用
所以:
in_addr_t inet_addr(const char*cp); //字符串表示的IPV4地址(点分十进制)转换为网络字节序列(无符号整型)
char* inet_ntoa(struct in_addr in); //IPV4地址的网络字节序列转化为字符串表示
三、网络编程常用接口
socket()创建套接字
bind()指定套接字使用的ip端口
listen()监听队列以及存储待处理的客户端连接
accept()接收连接,从listen监听的队列中接收一个连接
recv()接收数据
send()发送数据
close()关闭连接
connect()客户端向服务器发送连接请求
四、TCP编程流程编程
多进程多线程并发处理
如何使一个服务器同时接收多个客户端数据?
每次接收连接客户端,服务器端启动一个线程或进程
代码实现如下:
服务器端
客户端代码如下
运行结果如下
如上所示,两个不同的客户端进程向服务器同时发送内容
五、TCP协议特点
1.TCP协议特点:TCP协议是面向连接的、可靠的、字节流服务(可靠的体现在:应答确认,超时重传,乱序重排,去重)
2.TCP协议服务器端与客户端传输流程
3.三次握手四次挥手
三次握手:(向服务器发送连接(connect):三次握手开始的地方)
四次挥手:(关闭连接(close),四次挥手开始的地方)
4.流式服务特点
(1)
send()执行成功,只能说明将数据成功写入到发送端的发送缓冲区中,并不能说明数据已经发送到了对端。
recv()从本端的接收缓冲区中读取数据, 如果接收缓冲区中没有数据, 则recv()方法会阻塞。
例如:
(2)TCP粘包
什么是粘包?
多次发送的数据被对方一次收到
怎么解决粘包
方法一:在一段执行发送数据后,紧接着执行一次收数据(不连续发送数据,就不会粘包)
方法二:在解析发送的每个包时,对数据的起始和结论都做标记号
方法三:发送报文时,在报文头部添加长度位来描述该包的大小
5.TCP连接的状态
学习连接的状态前首先要知道tcp报头的6位标志位
(1)tcp报头的6位标志位
□URG 标志,表示紧急指针( urgent pointer) 是否有效。
□ACK 标志,表示确认号是否有效。我们称携带ACK 标志的 TCP 报文段为确认报文段。
□PSH标志, 提示接收端应用程序应该立即从TCP 接收缓冲区中读走数据, 为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在 TCP接收缓冲区中)。
□RST 标志,表示要求对方重新建立连接。我们称携带RST 标志的 TCP 报文段为复位报文段。
□SYN标志,表示请求建立一个连接。我们称携带SYN标志的 TCP 报文段为同步报文段。
□FIN标志, 表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP 报文段为结束报文段。
(2)tcp状态转移
(3)netstst查看状态的指令
(4)
如下图
(5)TIME_WAIT状态,如上图我们可知,TIME_WAIT状态是只有主动关闭的一端才会出现的状态。该状态一般持续时间为2个报文生存时间。
TIME_WAIT状态存在的原因
原因1:保证延迟的tcp报文有足够的时间被识别并丢弃
原因2:可靠的终止TCP连接