在 TCP 套接字中,发送和接收缓冲区用于暂存数据,以确保数据的可靠传输。具体来说,TCP 的 socket 收发缓冲区的主要特点和概念如下:
1. 发送缓冲区(Send Buffer)
定义: 发送缓冲区用于存储待发送的数据。应用程序将数据写入发送缓冲区,TCP 协议会将这些数据逐渐发送到网络中。
大小: 发送缓冲区的大小可以通过套接字选项进行配置,默认大小通常由操作系统决定。可以使用 setsockopt()
函数来修改送的缓冲区大小,例如:
int size = 1048576; // 1MB setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
2. 接收缓冲区(Receive Buffer)
定义: 接收缓冲区用于存储接收到的网络数据,通常由 TCP 协议管理。数据从网络中接收后,首先会存入接收缓冲区,应用程序随后从缓冲区中读取数据。
大小: 跟发送缓冲区一样,接收缓冲区的大小也可以通过 setsockopt()
调整。例如:
int size = 1048576; // 1MB setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
3. 缓冲区管理
TCP 是面向连接的协议,使用流控、拥塞控制等机制来管理数据传输。当发送缓冲区满时,发送操作会被阻塞,直到有数据被确认接收,腾出空间;同样,接收缓冲区满时,recv()
调用将阻塞,直到缓冲区有可读数据。
4. 缓冲区溢出
如果接收缓冲区的大小不够以存放所有传入的数据,丢失的数据将被丢弃。因此,合理设置缓冲区的大小对提升 TCP 性能是重要的。
5. 查看缓冲区大小(仅在 Linux 上)
使用 getsockopt()
函数可以查看当前缓冲区的大小。例如:
int size; socklen_t optlen = sizeof(size); getsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, &size, &optlen); printf("Send buffer size: %d\n", size); getsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &size, &optlen); printf("Receive buffer size: %d\n", size);
6. 影响因素
(1)网络带宽: 高带宽网络可能需要更大的发送和接收缓冲区。
(2)延迟和延迟带宽积: 高延迟的连接通常需要更大的缓冲区,以防止网络延迟导致的传输效率降低。
粘包:
粘包的原因:
-
TCP流的特性:TCP 是一种面向字节流的协议,无论发送方发送多少次数据,接收方可能在一次
recv
调用中接收到多个数据包,或者一个数据包被拆分为多个部分。 -
数据发送速率:发送方的连接速率快于接收方处理速率,造成多个数据在同一时间到达。
-
数据包大小差异:当小的数据包被频繁发送时,TCP 可能会将它们合并在一起以减少网络协议开销。
-
网络拥塞:网络拥塞可能会导致数据在发送过程中的堆积,从而导致粘包。
解决方案:
-
固定长度协议:每个数据包有固定的字节长度,接收方只需按此长度接收数据。
-
分隔符协议:在每个数据包后添加特定的分隔符(如
\n
、EOF
等),接收方通过检测分隔符来分割数据包。 -
消息头:在每个数据包前加上一个头部,头部包含消息体的长度信息。接收方先读取头部,知道完整消息的长度后,再读取相应字节的数据。
例如,可以设计如下数据格式:
[length][data]
其中
length
为数据长度(通常为 4 字节),data
为实际数据。 -
使用高层协议:使用已有的高层协议(如 HTTP、WebSocket 等),这些协议内置了解决粘包问题的机制
127.0.0.1
是一个特殊的IP地址,称为回环地址,通常用于网络测试和本地通信。它代表本地计算机或设备本身。使用这个地址,您可以在没有网络连接的情况下测试网络应用程序,因为所有通过该地址发送的数据都返回给同一设备。
二、recv和send
1. send
函数
send
函数用于在已连接的 socket 上发送数据。它的基本原型如下(C语言):
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-
参数说明:
sockfd
: 套接字描述符,标识已连接的 socket。buf
: 指向包含要发送数据的缓冲区的指针。len
: 要发送的数据的长度(字节数)。flags
: 发送操作的标志,通常可以为0。
-
返回值:
- 成功时返回实际发送的字节数;失败时返回 -1,并设置 errno。
2. recv
函数
recv
函数用于从连接的 socket 接收数据。它的基本原型如下(C语言):
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
-
参数说明:
sockfd
: 套接字描述符,标识已连接的 socket。buf
: 指向一个缓冲区,接收到的数据将存储在其中。len
: 缓冲区的大小(字节数)。flags
: 接收操作的标志,通常可以为0。
-
返回值:
- 成功时返回实际接收的字节数;返回值为0表示对方关闭了连接;失败时返回 -1,并设置 errno。
三、常用网络调试工具
ifconfig//查看主机上,网卡网络信息
ping//测试 两台主机之间是否连通
telnet//远程登录工具
ssh//硬件(开发板)
netstat// 查看当前主机上,活动的网络进程的相关的状态信息
arp
抓包
四、HTTP
1.http (超文本传输协议)
2.URL统一资源定位符