Вы игнорируете возвращаемое значение 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;
}
Кроме того, после чтения буфера вы рассматриваете его как нулевойопределяется, но это не так, поэтому вы получаете дополнительный мусор в выводе.
Что еще более важно, mapData != command.c_str()
всегда будет верным, поэтому ваш цикл while
будет повторяться бесконечно (пока не произойдет ошибка сокета), что не то, что вы хотите.Вы хотите, чтобы цикл завершился, когда вы получите вместо него строку "command> "
.
mapData
изначально имеет значение NULL, а c_str()
НИКОГДА не возвращает NULL, поэтому цикл ALWAYS повторяется хотя бы один раз.
Затем вы выделяете и освобождаете 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);