套接字和telnet出现问题
Having issues with sockets and telnet
我一直在学习套接字,我已经创建了一个基本服务器,您可以在其中telnet并键入消息,然后按enter键,消息就会打印在服务器上。
由于是telnet,每次按键都会发送到服务器。因此,我基本上将所有发送的字节都保存在缓冲区中,然后当收到回车("\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 = "rn"; // 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] = ' ';
}
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;
您有两个主要问题。
首先,您有一个变量receivedBytes
,它知道您收到的字节数。那你为什么叫strlen
?您不能保证收到的数据是C样式的字符串。例如,它可以包含嵌入的零字节。不要在上面调用strlen
。
其次,检查刚刚收到的rn
数据,而不是完整的接收缓冲区。并且您将数据接收到接收缓冲区的开头,而不是其中第一个未使用的空间。因此,如果一个对recv
的调用得到r
,下一个得到n
,那么您的代码将做错误的事情。
您从未真正编写代码来接收消息。您从未实际创建消息缓冲区来保存接收到的消息。
您的代码,我的评论:
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);
Bzzzzzzzzt。不能保证缓冲区中的任何位置都有null。你不需要这个变量。receivedBytes
中已存在正确的值。
for (int i = 0; i < siz_ar; i++)
这应该是`for(int i=0;i<receivedBytes;i++)
{
std::cout << std::hex << (int)receiveBuffer[i] << " " << std::dec;
}
std::cout << std::endl;
std::string stringCRLF = "rn"; // Carraige return representation
没有。这是一个回车(r
),后面跟着换行(n
),通常称为CRLF,因为变量名中确实有您自己。这是Telnet中的标准线路终止符。
std::string stringBS = "b"; // Backspace representation
std::string commandBuffer = receiveBuffer;
Bzzt。此副本的长度应由receivedBytes
分隔。
if (commandBuffer.find(stringCRLF) != std::string::npos)
正如@DavidShwartz所指出的,你不能假设你把CR和LF放在同一个缓冲区。
{
// 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] = ' ';
这没有任何意义。您使用strlen()
来告诉后面的null在哪里,然后在那里放一个null。您还遇到了一个问题,即可能没有的尾部null。在任何情况下,您都应该删除退格和前一个字符,这需要不同的代码。您还在错误的数据缓冲区上操作。
}
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());
}
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- C++格式化输出问题
- 套接字和telnet出现问题