【发布时间】:2016-08-26 15:18:18
【问题描述】:
我一直在学习套接字,并创建了一个基本服务器,您可以在其中远程登录并键入消息,然后按 Enter 键,消息将打印在服务器上。
由于是远程登录,每次按键都会发送到服务器。所以我基本上将所有发送的字节保存在一个缓冲区中,然后当收到回车符 ("\r\n") 时,我将其丢弃,并打印出客户端的当前缓冲区。然后我清除客户端缓冲区。
我的问题是每隔一段时间(我不太确定如何复制它),我发送的第一“行”数据会在每个字符上附加一个额外的空间。例如,我将在 telnet 客户端上键入“Test”,但我的服务器将接收它作为“T e s t”。我总是在接收任何数据之前清除接收缓冲区。一个明显的解决方案是删除服务器端的所有空格,但这会破坏我发送多个单词的能力。这只是我的 telnet 的问题,还是我可以在服务器上做些什么来解决这个问题?
我正在使用 WinSock2 API 和 Windows 10 Telnet。
编辑: 我检查了额外字符的十六进制值,它是 0x20。
编辑: 下面是接收和处理传入 telnet 数据的代码。
// This client is trying to send some data to us
memset(receiveBuffer, sizeof(receiveBuffer), 0);
int receivedBytes = recv(client->socket, receiveBuffer, sizeof(receiveBuffer), 0);
if (receivedBytes == SOCKET_ERROR)
{
FD_CLR(client->socket, &masterFDSet);
std::cerr << "Error! recv(): " << WSAGetLastError() << std::endl;
closesocket(client->socket);
client->isDisconnected = true;
continue;
}
else if (receivedBytes == 0)
{
FD_CLR(client->socket, &masterFDSet);
std::cout << "Socket " << client->socket << " was closed by the client." << std::endl;
closesocket(client->socket);
client->isDisconnected = true;
continue;
}
// Print out the hex value of the incoming data, for debug purposes
const int siz_ar = strlen(receiveBuffer);
for (int i = 0; i < siz_ar; i++)
{
std::cout << std::hex << (int)receiveBuffer[i] << " " << std::dec;
}
std::cout << std::endl;
std::string stringCRLF = "\r\n"; // Carraige return representation
std::string stringBS = "\b"; // Backspace representation
std::string commandBuffer = receiveBuffer;
if (commandBuffer.find(stringCRLF) != std::string::npos)
{
// New line detected. Process message.
ProcessClientMessage(client);
}
else if (commandBuffer.find(stringBS) != std::string::npos)
{
// Backspace detected,
int size = strlen(client->dataBuffer);
client->dataBuffer[size - 1] = '\0';
}
else
{
// Strip any extra dumb characters that might have found their way in there
commandBuffer.erase(std::remove(commandBuffer.begin(), commandBuffer.end(), '\r'), commandBuffer.end());
commandBuffer.erase(std::remove(commandBuffer.begin(), commandBuffer.end(), '\n'), commandBuffer.end());
// Add the new data to the clients data buffer
strcat_s(client->dataBuffer, sizeof(client->dataBuffer), commandBuffer.c_str());
}
std::cout << "length of data buffer is " << strlen(client->dataBuffer) << std::endl;
【问题讨论】:
-
您的额外空间是真实空间吗?或任何其他不可打印的字符?
-
您应该为第二个问题打开一个新问题,因为您的两个问题根本没有关联。无论如何,处理任何平台的解决方案是等待
\r或\n或\r\n。 -
@kadriles ,我检查了传入数据的十六进制值,多余的字符是0x20,所以它是一个实际的空间。另外,我将删除第二个问题/移动它。
-
请出示您的代码。否则就没有办法(纯粹的推测除外)来诊断问题。
-
\r\n是回车后跟换行符,而不仅仅是回车。接收缓冲区的长度由receivedBytes给出,而不是由strlen()给出。在strlen()已经找到的地方放置一个空值没有任何意义。
标签: c++ sockets winsock telnet