嵌入式学习----TCP和UDP通信的内核实现

loop本地回环
Loop本地回环,通常指的是以127开头的IP地址段(127.0.0.1 – 127.255.255.254),其中127.0.0.1是最常用的一个地址,被称为本地回环地址(Loop back address)。这个地址不属于任何一个有类别地址类,它代表设备的本地虚拟接口,因此默认被看作是永远不会宕掉的接口。在Windows操作系统中也有相似的定义,所以在不安装网卡前就可以ping通这个本地回环地址。

Loop本地回环的主要作用包括:

测试本机的网络配置:通过ping 127.0.0.1,可以检查本机的网卡和IP协议安装是否正常。如果能成功ping通,说明本机的网络配置基本没有问题。

TCP通信产生的粘包问题
粘包问题是TCP/IP通信中常见的一个问题,主要源于TCP的流式传输特性。在TCP协议中,数据是以流(stream)的形式传输的,这种流数据没有明确的数据开始和结尾边界,因此容易出现粘包现象。具体来说,当发送方连续发送多个数据包时,由于TCP的缓冲机制,这些数据包可能会被合并成一个大的数据包发送给接收方,或者在接收方由于接收缓冲区的原因,多个数据包被合并在一起处理,这就是粘包现象。

粘包问题的原因主要有两个方面:
发送方原因:TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。


接收方原因:接收方用户进程不及时接收数据,导致多个数据包在接收方的缓冲区中粘连在一起,当后续数据到达时,这些数据包被一起处理,从而产生粘包现象。


粘包问题的解决方法:
1.使用特定结束符:
在每个数据包的末尾添加特定的结束符(如换行符\n),接收方在接收到数据时,根据结束符来区分数据包的边界。这种方法需要注意避免数据包内容中出现与结束符相同的字符,否则可能会导致误判。


2.固定数据大小:
发送方和接收方约定每个数据包的大小,当发送的数据不足约定大小时,用空字符或其他填充字符补齐。这种方法简单但不够灵活,且会增加额外的网络传输负担。


3.封装自定义数据协议:
在TCP协议的基础上封装一层自定义数据协议,该协议中包括数据头和数据体两部分。数据头中存储了数据体的大小等信息,接收方在接收到数据后,先解析数据头,根据数据头中的信息来提取数据体,从而避免粘包问题。这种方法实现起来相对复杂,但灵活性高,适用于多种场景。

4.还可以使用sleep这种延时的方式来解决,但对于时间精度的把握难度会很大。

recv函数和send函数:(专用于网络编程的read和write)
recv函数原型
recv函数的主要功能是从已连接的套接字接收数据。

#include <sys/types.h>

#include <sys/socket.h>

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

 参数:
sockfd/socket:套接字描述符/socket对象,用于标识要接收数据的套接字。


buf:指向缓冲区的指针/缓冲区,用于存储接收到的数据。在C语言中,它是一个void类型的指针。


len:缓冲区长度/bufsize,指定接收数据的最大字节数。如果接收到的数据大于这个长度,则多余的数据将被丢弃;如果小于这个长度,则实际接收到的数据将被存储在缓冲区中。


flags(可选):用于指定接收数据的额外选项。一般设置为0,常见的选项包括MSG_WAITALL(等待所有数据到达)和MSG_DONTWAIT(非阻塞模式)等。


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


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


 send函数:
用于实现数据的发送功能。

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

 参数:
sockfd:套接字描述符,一个指向已打开套接字的引用,该套接字已连接到远端地址。
buf:指向要发送数据的缓冲区的指针。
len:指定要发送的数据的字节数。
flags:发送操作的控制标志。对于大多数应用程序,这个参数被设置为 0,但在某些情况下,可以指定特定的标志来修改 send 的行为。


返回值
成功时,send 函数返回实际发送的字节数。这个数可能小于请求发送的字节数,尤其是在非阻塞套接字上或者发送缓冲区已满时。
如果发送过程中出现错误,send 函数返回 -1,并设置相应的 errno 以指示错误的类型。


注意事项
1.send 函数在大多数情况下是阻塞的,即如果发送缓冲区已满,调用 send 的线程或进程将被挂起,直到发送缓冲区中有足够的空间可以容纳要发送的数据或发生错误。
可以通过设置套接字为非阻塞模式或使用 select/poll/epoll 等机制来避免阻塞。


2.在 TCP/IP 协议中,发送的数据可能会被分成多个数据包进行传输,并且这些数据包可能会以不同的顺序到达接收端。但是,TCP 协议保证了数据的完整性和顺序性,即接收端将按照发送的顺序接收并重新组装这些数据包。
由于网络延迟、拥塞等原因,send 函数可能无法立即发送所有数据。因此,在需要发送大量数据时,可能需要编写循环来不断发送数据,直到所有数据都被发送完毕。
在某些情况下,如发送非阻塞套接字上的数据时,send 函数可能返回小于请求发送的字节数的值,表示只有部分数据被发送。此时,应用程序需要处理这种情况,通常是通过再次调用 send 函数来发送剩余的数据。

TCP协议运输层的底层实现

TCP(传输控制协议)的首部是TCP协议数据包中的一个关键部分,它包含了用于传输控制的各种重要信息。TCP虽然是面向字节流的,但其传送的数据单元是报文段,一个TCP报文段分为首部和数据两部分。

1. 固定部分(前20个字节)
源端口(Source Port):占2个字节,用于标识发送该TCP报文段的应用进程的端口号。


目的端口(Destination Port):占2个字节,用于标识接收该TCP报文段的应用进程的端口号。


序号(Sequence Number):占4个字节,用于标识发送方发送的数据段。序号范围是[0, 232 - 1],序号增加到232-1后,下一个序号就回到0。TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。


确认号(Acknowledgment Number):占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。例如,如果B正确收到了A发送的一个序号为501、长度为200字节的报文段,那么B期望收到的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。


数据偏移(Data Offset):占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远(以32位字即4字节为计算单位)。这个字段实际上是指出TCP报文段的首部长度,其最大值为15(即60字节),这也是TCP首部的最大长度。


保留(Reserved):占6位,保留为今后使用,但目前应置为0。


控制位(Control Bits):共6位,用于说明本报文段的性质,包括确认ACK、推送PSH、复位RST、同步SYN、终止FIN等。
ACK:仅当ACK=1时确认号字段才有效,TCP规定,在连接建立后所有传送的报文段都必须把ACK置为1。
PSH:当两个应用进程进行交互式的通信时,TCP可以使用推送操作,发送方TCP把PSH置1,并立即创建一个报文段发送出去。
RST:当RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接。
SYN:在连接建立时用来同步序号,当SYN=1而ACK=0时,表明这是一个连接请求报文段。
FIN:用来释放一个连接,当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。

窗口(Window):占2字节,窗口值是[0, 2^16-1]之间的整数,窗口指的是发送本报文段的一方的接收窗口(而不是自己的发送窗口)。窗口值告诉对方,从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(以字节为单位)。


检验和(Checksum):占2字节,用于检查数据的完整性和正确性,其检验的范围包括首部和数据这两部分。


紧急指针(Urgent Pointer):占2字节,紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。
2. 可选部分
TCP报文段首部后面还可以有4n字节(n为整数)的可选字段,这些字段是根据需要而增加的,用于支持TCP的各种扩展功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值