通过套接字 c++ 发送长度和数据
Send length and data through socket c++
所以我目前正在开发一个使用套接字的应用程序,目前一切正常,我只想知道是否有更有效的方法来发送数据和数据的长度而不是发送两次。
即:在一个字符串中发送所有内容。
void SendPackage(const SOCKET sock, const std::string package)
{
int length = package.lenth();
send(sock, std::to_string(length).c_str(), 10, 0); //Buffer length is 10 assuming data length
send(sock, package.c_str(), length, 0); //will never be greater than 9,999,999,999
}
void ReceivePackage(const SOCKET sock, std::string &package, int bufferLength)
{
std::vector<char> recvBuffer(10);
int length, bytesProcessed;
recv(sock, &recvBuffer[0], 10, 0); //Receiving length
length = atoi(&recvBuffer[0]);
recvBuffer.resize(length);
for (int i = 0; i < length; i += bytesProcessed)
{
bytesProcessed = recv(sock, &recvBuffer[0] + i, bufferLength, 0);
if (bytesProcessed < 0) break;
}
package = &recvBuffer[0];
}
send(sock, std::to_string(length).c_str(), 10, 0);
这是 UB。你告诉它数据有 10 个字节,但这是不正确的。除此之外,没有必要将你的int转换为字符串,然后发送字符串。刚刚发送了int,为了避免任何平台不兼容,我建议使用固定大小的类型:
std::int32_t length = package.length();
send(sock, &length, sizeof(length), 0);
在接收端,您必须确保实际等待所有字节都在那里。您不能简单地调用recv
并假设它为您提供所需的所有字节。你需要在循环中调用它并检查它的返回值,它告诉你你得到了多少字节。要接收length
,您需要将适当数量的字节读取到缓冲区中,然后将该缓冲区重新解释为您选择的类型(例如std::int32_t
.
此外,您应该确保 int 的字节序正确。对网络数据使用大端序是事实上的标准,但归根结底,这取决于您。不是标准(afaik(的一部分,但在常见平台上可用的是辅助函数htonl
和ntohl
,它们代表"主机到网络,长"和"网络到主机,长"。它们获取并返回一个std::int32_t
,您可以简单地使用它们来确保字节序对双方都有效。
寄件人:
std::int32_t length = htonl(package.length());
send(sock, &length, sizeof(length), 0);
接收器:
// after successfully reading all bytes for the length value into an adequately sized buffer:
std::int32_t length = ntohl(*reinterpret_cast<std::int32_t*>(buffer));
就套接字接口而言,您不会发送两次。套接字只是通过一个或多个send
调用将您塞入一端的所有内容,并在自己的时间内将其发送出去(我假设您在第一次调用时不会超过套接字缓冲区,这是一个相当安全的假设(。同样,您无需将recv
呼叫与send
呼叫进行匹配。你可以一次recv
全部,然后再分解,但实际上,这样做没有太大的收获。
因此,无论您是先打包字符串然后发送,还是send
两次调用,这真的是一种洗涤。创建长度连接到开头的新字符串所需的时间和 RAM 不会比只调用两次send
更有效。
但是,您绝对应该将长度作为它出现int
发送,而不是作为字符串发送。这样它将始终占用sizeof(int)
个字节。10
的缓冲区长度通常不为真,并导致读取字符串的末尾。例如:
send(sock, &length, sizeof(length), 0);
和
recv(sock, &length, sizeof(length), 0); //Receiving length
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- WTSEnumerateProcesses与套接字和数据结构
- 在 1 个服务器 n 客户端套接字 C++ MFC 应用程序中更新数据的客户端
- C++ TCP 套接字通信 - 连接按预期工作,几秒钟后失败,没有收到新数据,read() 和 recv() 块
- 我们可以在套接字编程中将自定义数据作为辅助数据发送吗?
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 尝试将数据从C++发送到 Python 并使用套接字C++反转,C++ sendto() 和 python recvfr
- 不要从输入队列套接字读取数据
- 通过套接字 c++ 发送长度和数据
- 如何读取套接字编程(c ++)中的所有数据?
- 使用 Broadcast 发出的从节点服务器发送的数据不能被 C++ 套接字 IO 客户端读取
- 无法通过套接字发送或接收数据
- 连接UDP套接字,但仍然接收来自其他源的数据报
- boost::asio-async_read_some示例代码没有读取套接字中的所有数据
- 使用 epoll 边缘触发器的套接字上的数据过多
- 为什么 sys 套接字 recv 函数不填充数据但返回字节长度?
- 将空数据写入非阻塞套接字会导致epoll_wait挂起
- C++ 套接字 - 发送 - 未收到数据
- 通过套接字发送的自定义数据包
- 提升ASIO TCP,为什么我不能在服务器端只有一个数据套接字可以打开和关闭