recv() returns 奇怪的缓冲区 C++

recv() returns strange buffer C++

我了解 C++ 很长时间了,但大约一年半前开始将其用于我的目的。 我开始在 C++ 上学习网络编程,第一个网络项目是“通过 TCP/IP 在主机之间传输文件”,这听起来很简单,但我一直坚持发送数据。

我正在尝试发送小于 4KB 的小缓冲区,因此缓冲区 [4096] 对我来说工作正常,但我打算扩展它。 WSAStartup()、socket()、bind()、listen()、accept() 函数工作正常,并且它们的值已为服务器和客户端初始化,但我正在处理其他问题,也许是 recv()、send()等等 我仍然找不到问题的根源。

此外,如果有人给我一个通过 TCP/IP 传输文件的示例,但不是在一个数据包中,我希望文件被分块并分段发送,或者正如它所谓的“戒指模型”,但我找不到可用的模型;

P.S。这是我第一次在这里提问,请反馈一下所有这些写得如何,这样我就可以写更多的信息来帮助社区,谢谢)

服务器

char* buffer = new char[4096];
ZeroMemory(buffer, sizeof(buffer));
ofstream file("a.txt", ios::binary);
int err = recv(conn, buffer, sizeof(buffer), 0);
file << buffer;
file.close();
if (err == 0)
{
    printf("Client diconnected...\n");
}

printf("Quitting...\n");
delete[] buffer;

客户

ifstream file("a.txt", ios::binary);
file.seekg(0, ios::end);
int size = file.tellg();
file.seekg(0, ios::beg);
char* buffer = new char[size];
file.read(buffer, size);
file.close();

int err = send(client, buffer, size, 0);
if (err == 0)
{
    printf("Disconnecting...\n");
}

printf("Quitting...\n");
delete[] buffer;

"a.txt" 客户端的文件是 45 字节,这里是 45 * 'a'

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

这是我在服务器端得到的,文件大小是 14 字节

aaaaaaaa ’pÈ/

在C++中,sizeof(buffer)是指针类型的大小。

您可能想阅读更现代的(如 1998 年之后)C++。我们现在有 std::vector,那有一个方便的 size 方法。它将 return 4096 作为您的缓冲区。此外,矢量句柄 new[]delete[] 为您服务。

您获得 8 个“a”的事实表明您是为 x64 构建的。剩下的字节是垃圾;您应该检查 recv 实际写入 buffer 的字节数。你不能假设你得到了你要求的所有字节(无论是 8 还是 4096)。

MSDN 声明:

If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero.

Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv

测试你是否真的读取了 45 个字节并检查是否有错误(WSAGetLastError 函数)

我相信这一行中的 sizeof(buffer) -->

int err = recv(conn, buffer, sizeof(buffer), 0);

will return sizeof(char*) 在 32 位程序中是 4 个字节,在 64 位程序中是 8 个字节而不是 4096,因为它不是静态数组,因为你没有声明它作为字符缓冲区 [4096]。因此,要么将其声明为 char buffer[4096],要么将上面的代码转换为

int err = recv(conn, buffer, 4096, 0);

另外两点:

  • TCP 是一种流协议(不是“基于消息的”),因此不能保证单个 recv() 会在单个 send() 中发送所有内容。

  • 服务器行 file << buffer; 假设 buffer 是零终止的。