2024年8月23日嵌入式学习

今日主要学习tcp的数据传输

### Loop本地回环

Loop本地回环通常指的是一段以127开头的IP地址(127.0.0.1 至 127.255.255.254),其中127.0.0.1是最常用的地址,被称为本地回环地址(Loopback Address)。该地址不属于任何特定的地址类别,代表设备的本地虚拟接口,因此被视为永远不会宕掉的接口。在Windows操作系统中也有类似的定义,因此即使在没有安装网卡的情况下,仍然可以ping通这一本地回环地址。

#### Loop本地回环的主要作用:

1. **测试本机的网络配置**:通过执行`ping 127.0.0.1`命令,可以检查本机的网卡和IP协议是否正常工作。如果能够成功ping通,说明本机的网络设置一般没有问题。

2. **应用程序的资源调用**:在某些客户端/服务器应用程序中,当需要调取服务器上的资源时,如果这些程序在同一台设备上运行且没有其他服务器,资源可以在本地环境中被调用,服务器的IP地址可以设置为127.0.0.1,程序便可正常运行。

---

### 粘包问题

粘包问题是TCP/IP通信中常见的现象,主要源于TCP的流式传输特性。在TCP协议中,数据以流的形式传送,这种流没有明确的起始和结束边界,因此容易出现粘包的情况。当发送方连续发送多个数据包时,由于TCP的缓冲机制,这些数据可能会被合并成一个较大的数据包进行发送,或者在接收方,由于接收缓冲区的限制,多个数据包被合在一起处理。

##### 粘包问题的原因:

1. **发送方原因**:为了提高传输效率,发送方通常会在积累到一定量的数据之后再发送,如果连续发送的数据量较小,TCP可能会将多条数据合并成一个包发送,这样接收方就可能接收到了粘包数据。

2. **接收方原因**:接收方进程未能及时处理数据,导致多个数据包在缓冲区内黏连在一起,当新数据到达时,它们可能被一起处理,由此产生粘包现象。

##### 粘包问题的解决方法:

1. **使用特定结束符**:在每个数据包的末尾添加特定的结束符(如换行符 `\n`),接收方在接收到数据时可以根据结束符来判断数据包的边界。这种方法实现较为简单,但需要避免在数据内容中出现结束符,以防止出现误判。

2. **固定数据大小**:发送方与接收方约定数据包的大小,当发送的数据不足约定大小时,可以用空字符或其他填充字符进行补齐。这种方式较为简单,但灵活性不足,且会增加网络传输的负担。

3. **封装自定义数据协议**:在TCP协议之上,构建一层自定义数据协议,此协议包含数据头和数据体两部分。数据头中会存储数据体的大小等信息,接收方接收到数据后,会先解析数据头,根据其中的信息提取相应的数据体,从而避免粘包问题。这种方法虽然实现起来较为复杂,但灵活性较高,适用于各种场景。

### recv函数和send函数

#### recv函数


recv函数的主要作用是从已连接的套接字接收数据。

```c
#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
```

**参数说明:**
- `sockfd`:套接字描述符,用于标识要接收数据的套接字。
- `buf`:指向接收数据的缓冲区的指针。在C语言中,它是一个void类型的指针。
- `len`:缓冲区的大小,指定接收的最大字节数。如果接收到的数据超过该长度,多余的数据将被丢弃;如果实际接收到的数据小于这个长度,则数据将存储在缓冲区中。
- `flags`(可选):指定接收数据的附加选项,通常设置为0。常见选项有MSG_WAITALL(等待所有数据到达)和MSG_DONTWAIT(非阻塞模式)。

**返回值:**
- 成功时,返回接收到的字节数。如果连接正常关闭,则返回0。
- 若发生错误,返回-1,并设置errno以指示错误类型。

**注意事项:**
- recv函数是阻塞的,这意味着若套接字上没有可读数据,调用recv的线程将被挂起,直到数据到达或发生错误。
- 可以通过设置套接字为非阻塞模式或使用select/poll/epoll等机制来避免阻塞。
- 实际应用中,由于网络延迟或拥塞,recv可能无法一次性接收全部数据,因此通常需要编写循环不断接收数据,直到达到预期数据量或遇到特定结束标志。
- 接收到的数据可能不会完全以发送时的形式呈现,因TCP/IP协议栈可能对数据进行了分片或重新排序。因此,在接收端可能需要对数据进行重组或解析。

#### send函数


send函数用于发送数据。

```c
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
```

**参数说明:**
- `sockfd`:套接字描述符,指向已连接的套接字。
- `buf`:指向要发送的数据缓冲区的指针。
- `len`:要发送的数据字节数。
- `flags`:控制发送行为的选项,通常设置为0,但在某些情况下,可以指定特定标志来修改send的行为。

**返回值:**
- 成功时,send函数返回实际发送的字节数,这个数可能小于请求发送的字节数,特别是在使用非阻塞套接字或发送缓冲区已满时。
- 发送过程中若发生错误,send函数返回-1,并设置errno以指示错误类型。

**注意事项:**
- send函数通常是阻塞的,即如果发送缓冲区已满,调用send的线程将被挂起,直到缓冲区有足够空间可以容纳数据或发生错误。
- 可以通过设置套接字为非阻塞模式或使用select/poll/epoll等机制来避免阻塞。
- 在TCP/IP协议中,发送的数据可能会被拆分成多个数据包进行传输,并且这些数据包可能会以不同的顺序到达接收端。然而,TCP协议保证了数据的完整性和顺序性,接收端将按发送顺序接收并重新组装这些数据包。
- 由于网络延迟或拥塞,send函数可能无法立即发送所有数据,因此在发送大量数据时,通常需要编写循环以不断发送数据,直到所有数据都被发送完毕。
- 在某些情况下,尤其是在发送非阻塞套接字上的数据时,send函数可能返回小于请求发送字节数的值,表示只有一部分数据被发送。在此情况下,应用程序需要处理这种情况,通常通过再次调用send函数来发送剩余数据。

### TCP协议特点:


1. **面向连接**:TCP在进行数据传输前,需先与对方建立连接,即执行三次握手,以确保通讯双方都已准备就绪,连接成功后才能开始数据交换。

2. **可靠传输**:TCP通过确认应答、超时重传、错误检测等机制确保数据可靠性。如果在传输中数据发生错误或丢失,TCP会自动重传,直到数据顺利接收。

3. **基于字节流**:TCP不维持报文边界,将应用传送的数据视为一连串字节进行传递。

### UDP协议特点:


1. **无连接**:UDP在数据传输前无需建立连接,发送方只需将数据打包成UDP数据报并发送,这种特性使得UDP通信过程更为简单、快速。

2. **不可靠**:UDP不保证数据可靠性,它只负责将数据报送出,而不关注数据是否成功到达接收方。如传输中出现错误或数据丢失,UDP不会进行重发或恢复操作。

3. **基于数据报**:UDP保留了报文边界,发送方发送的每个数据报在接收方都作为独立单元处理,非常适合于实时性要求高且对丢包不敏感的数据传输。

### 常用的网络测试工具:

- **Wireshark抓包工具**:用于网络协议分析和数据包捕获的重要工具。

### TCP首部结构


TCP(传输控制协议)的首部是TCP协议数据包的关键组成部分,包含了用于传输控制的重要信息。虽然TCP是面向字节流的,但其传递数据的单位是报文段,每个TCP报文段由首部和数据两部分组成。以下是TCP首部主要字段的详细解析:

1. **固定部分(前20个字节)**
   - **源端口(Source Port)**:占2个字节,用来标识发送TCP报文段的应用进程的端口号。
   - **目的端口(Destination Port)**:占2个字节,用于标识接收TCP报文段的应用进程的端口号。
   - **序号(Sequence Number)**:占4个字节,用于标识发送方的数据段。序号范围为[0, 2^32 - 1],当序号增至225-1时,下一序号将回到0。TCP是字节流协议,字节在连接中都有顺序编号。
   - **确认号(Acknowledgment Number)**:占4个字节,表示期望收到的下一个报文段的第一个数据字节序号。例如,若B收到了A发送的序号为501的报文段,长度为200字节,则B的确认号应为701,表示期待收到序号为701的数据。
   - **数据偏移(Data Offset)**:占4位,用于指出数据起始位置距离TCP报文段起始的距离(以32位字即4字节为单位),也表示TCP报文段的首部长度,最大为15(即60字节)。
   - **保留(Reserved)**:占6位,未来可能用作扩展,目前应置为0。
   - **控制位(Control Bits)**:共6位,用于指示该报文段的性质,包括ACK(确认)、PSH(推送)、RST(复位)、SYN(同步)、FIN(终止)等。
     - **ACK**:仅当ACK=1时确认号字段有效,连接建立后所有报文段的ACK必为1。
     - **PSH**:在交互式通信时,发送方TCP可设为1,立即发送该报文段。
     - **RST**:当RST=1时,表示TCP连接中出现错误,需释放原连接并重新建立。
     - **SYN**:在连接建立时用以同步序号,当SYN=1且ACK=0时,指示这是连接请求的数据段。
     - **FIN**:用于释放连接,FIN=1表示发送方的数据已发送完毕,要求释放连接。
   - **窗口(Window)**:占2字节,表示从确认号算起的接收窗口大小(字节单位),告知对方当前接收允许的字节量。
   - **检验和(Checksum)**:占2字节,用于校验数据的完整

2. 可选部分

TCP报文段首部后面还可以有4n字节(n为整数)的可选字段,这些字段是根据需要而增加的,用于支持TCP的各种扩展功能。

三次握手

四次挥手

 UDP首部结构

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值