gpt4 book ai didi

c++ - 在 C++ 中从服务器读取二进制数据时清除缓冲区

转载 作者:行者123 更新时间:2023-11-27 23:42:24 24 4
gpt4 key购买 nike

我有一个服务器发送原始二进制数据来打印用户必须遍历的“ map ”,但是,我在读取每一行后清除缓冲区时遇到问题,因此在较短的线。在下面的屏幕截图中,您可以在左侧看到我的输出,在右侧看到应该 的输出。解决这个问题的最佳方法是什么?我觉得我错过了什么,但似乎找不到解决办法。

enter image description here

读取/打印的代码如下:

char* mapData = NULL;
string command = "command> ";
size_t dataSize = 0;
while(mapData != command.c_str()) {
unsigned char* buffer = (unsigned char*) &dataSize;
connection = read(mySocket, buffer, 8);
if(connection == -1 || connection < 0) {
cerr << "**Error: could not read text size" << endl;
return 1;
}

mapData = (char*)malloc(dataSize);
buffer = (unsigned char*) mapData;

while((connection = read(mySocket, buffer, dataSize)) != -1) {
if(connection == -1 || connection < 0) {
cerr << "**Error: could not read text size" << endl;
return 1;
}
if(dataSize != 1) {
cout << buffer;
}
free(buffer);
buffer = NULL;
}

}

最佳答案

您忽略了 read() 的返回值以了解缓冲区中有多少字节。

read() 返回已读取的实际字节数,这可能比您请求的要少。所以你需要在循环中调用 read() 直到你读取了所有你期望的字节,例如:

int readAll(int sock, void *buffer, size_t buflen)
{
unsigned char* pbuf = reinterpret_cast<unsigned char*>(buffer);
while (buflen > 0) {
int numRead = read(sock, pbuf, buflen);
if (numRead < 0) return -1;
if (numRead == 0) return 0;
pbuf += numRead;
buflen -= numRead;
}
return 1;
}

此外,在读取缓冲区后,您将其视为以 null 结尾的,但事实并非如此,这就是您在输出中得到额外垃圾的原因。

更重要的是,mapData != command.c_str() 将始终为真,因此您的 while 循环会无限期地迭代(直到发生套接字错误),这不是你想要什么。您希望在收到 "command> " 字符串时结束循环。

mapData 最初为 NULL,而 c_str() 永远不会返回 NULL,因此循环总是至少迭代一次。

然后您分配并释放 mapData 但不将其重置为 NULL,因此它仍指向无效内存。这并不重要,因为您的 while 循环只是比较指针。 c_str() 永远不会返回指向 mapData 曾经指向的内存的指针。

要正确结束循环,您需要在读取后比较 mapData内容,而不是比较其内存地址

试试这个:

char *mapData = NULL;
uint64_t dataSize = 0;
const string command = "command> ";
bool keepLooping = true;

do {
if (readAll(mySocket, &dataSize, sizeof(dataSize)) <= 0) {
cerr << "**Error: could not read text size" << endl;
return 1;
}

if (dataSize == 0)
continue;

mapData = new char[dataSize];

if (readAll(mySocket, mapData, dataSize) <= 0) {
cerr << "**Error: could not read text" << endl;
delete[] mapData;
return 1;
}

cout.write(mapData, dataSize);

keepLooping = (dataSize != command.size()) || (strncmp(mapData, command.c_str(), command.size()) != 0);

delete[] mapData;
}
while (keepLooping);

或者:

string mapData;
uint64_t dataSize = 0;
const string command = "command> ";

do {
if (readAll(mySocket, &dataSize, sizeof(dataSize)) <= 0) {
cerr << "**Error: could not read text size" << endl;
return 1;
}

mapData.resize(dataSize);

if (dataSize > 0) {
if (readAll(mySocket, &mapData[0], dataSize) <= 0) {
cerr << "**Error: could not read text" << endl;
return 1;
}

cout << mapData;
}
}
while (mapData != command);

关于c++ - 在 C++ 中从服务器读取二进制数据时清除缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53459312/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com