字符数组中的十六进制在写入套接字时导致随机字符
Hex in char array resulting in random character when writing to socket
与外部系统通信时,他们希望我在响应末尾添加一个空字节。但是我遇到了一些问题:
//reading from socket
//sending response
std::string response = "hardcodedResponse";
int bufferSize = response.size() + 1; // +1 for the trailing zero
char buffer[bufferSize];
for (int i = 0; i < response.size(); i++)
{
buffer[i] = response[i];
}
buffer[bufferSize] = 0x00;
int socketfd = 1;
unsigned bytesWritten = 0;
while (bytesWritten < bufferSize)
{
bytesWritten += ::write(socketfd, buffer[bytesWritten], bytesToWrite - bytesWritten);
}
当我使用 telnet 向套接字发送内容时,我收到了一个响应:"hardcodedResponse" 后跟一个 ▒。我认为这是有道理的,因为 0x00 是空的。但是,如果我在末尾添加 0x41 (A),我会收到 "hardcodedResponse" + 一个(看似)随机字符。如果我在写入套接字之前打印缓冲区的最后一个字符,它会打印 'A'。如果外部系统也能收到正确的字节,这并不重要,但是,他们收到的是随机字节。
我不知道为什么会这样。希望有人能帮我理解。
除了所有套接字之外,还要查看缓冲区长度以及放置空值的位置:
std::string response = "hardcodedResponse";
int bufferSize = response.size() + 1; // +1 for the trailing zero
char buffer[bufferSize]; //Up to, but not including bufferSize
//0, 1, ... bufferSize-1
for (int i = 0; i < response.size(); i++)
{
buffer[i] = response[i];
}
buffer[bufferSize] = 0x00; //BOOM udefined behaviour
您为 null 添加了一个额外的字符,而不是两个,因此将 null 放在末尾而不是超出末尾。
buffer[bufferSize-1] = 0x00;
首先,您依赖于称为 "Variable Length Arrays" 的非标准功能。只有少数 C++ 编译器支持 VLA,并且仅作为可选扩展。对于动态大小的数组,您应该使用 STL std::vector
容器。
但是,更重要的是,您将空字节写入了错误的数组索引。 buffer[]
中的有效索引范围是 0..bufferSize-1
。写入 buffer[bufferSize]
不会在数据末尾的正确位置附加空终止符,并且会破坏周围的内存。
你需要改变这个:
buffer[bufferSize] = 0x00;
为此:
buffer[bufferSize-1] = 0x00;
您也没有正确管理对 write()
的调用。特别是,它可以 return -1 错误,您没有处理。你应该使用 bufferSize
而不是 bytesToWrite
.
也就是说,您实际上根本不需要 buffer[]
数组,您可以按原样发送 std::string
数据:
//sending response
std::string response = "hardcodedResponse";
const char *buffer = response.c_str();
const size_t bufferSize = response.size() + 1; // +1 for the trailing zero
size_t totalWritten = 0;
ssize_t bytesWritten;
do
{
bytesWritten = ::write(socketfd, buffer[totalWritten], bufferSize - totalWritten);
if (bytesWritten <= 0)
{
// handle error...
break;
}
totalWritten += bytesWritten;
}
while (totalWritten < bufferSize);
或:
//sending response
std::string response = "hardcodedResponse";
const char *buffer = response.c_str();
size_t bufferSize = response.size() + 1; // +1 for the trailing zero
size_t totalWritten = 0;
ssize_t bytesWritten;
do
{
bytesWritten = ::write(socketfd, buffer, bufferSize);
if (bytesWritten <= 0)
{
// handle error...
break;
}
buffer += bytesWritten;
bufferSize -= bytesWritten;
}
while (bufferSize > 0);
与外部系统通信时,他们希望我在响应末尾添加一个空字节。但是我遇到了一些问题:
//reading from socket
//sending response
std::string response = "hardcodedResponse";
int bufferSize = response.size() + 1; // +1 for the trailing zero
char buffer[bufferSize];
for (int i = 0; i < response.size(); i++)
{
buffer[i] = response[i];
}
buffer[bufferSize] = 0x00;
int socketfd = 1;
unsigned bytesWritten = 0;
while (bytesWritten < bufferSize)
{
bytesWritten += ::write(socketfd, buffer[bytesWritten], bytesToWrite - bytesWritten);
}
当我使用 telnet 向套接字发送内容时,我收到了一个响应:"hardcodedResponse" 后跟一个 ▒。我认为这是有道理的,因为 0x00 是空的。但是,如果我在末尾添加 0x41 (A),我会收到 "hardcodedResponse" + 一个(看似)随机字符。如果我在写入套接字之前打印缓冲区的最后一个字符,它会打印 'A'。如果外部系统也能收到正确的字节,这并不重要,但是,他们收到的是随机字节。
我不知道为什么会这样。希望有人能帮我理解。
除了所有套接字之外,还要查看缓冲区长度以及放置空值的位置:
std::string response = "hardcodedResponse";
int bufferSize = response.size() + 1; // +1 for the trailing zero
char buffer[bufferSize]; //Up to, but not including bufferSize
//0, 1, ... bufferSize-1
for (int i = 0; i < response.size(); i++)
{
buffer[i] = response[i];
}
buffer[bufferSize] = 0x00; //BOOM udefined behaviour
您为 null 添加了一个额外的字符,而不是两个,因此将 null 放在末尾而不是超出末尾。
buffer[bufferSize-1] = 0x00;
首先,您依赖于称为 "Variable Length Arrays" 的非标准功能。只有少数 C++ 编译器支持 VLA,并且仅作为可选扩展。对于动态大小的数组,您应该使用 STL std::vector
容器。
但是,更重要的是,您将空字节写入了错误的数组索引。 buffer[]
中的有效索引范围是 0..bufferSize-1
。写入 buffer[bufferSize]
不会在数据末尾的正确位置附加空终止符,并且会破坏周围的内存。
你需要改变这个:
buffer[bufferSize] = 0x00;
为此:
buffer[bufferSize-1] = 0x00;
您也没有正确管理对 write()
的调用。特别是,它可以 return -1 错误,您没有处理。你应该使用 bufferSize
而不是 bytesToWrite
.
也就是说,您实际上根本不需要 buffer[]
数组,您可以按原样发送 std::string
数据:
//sending response
std::string response = "hardcodedResponse";
const char *buffer = response.c_str();
const size_t bufferSize = response.size() + 1; // +1 for the trailing zero
size_t totalWritten = 0;
ssize_t bytesWritten;
do
{
bytesWritten = ::write(socketfd, buffer[totalWritten], bufferSize - totalWritten);
if (bytesWritten <= 0)
{
// handle error...
break;
}
totalWritten += bytesWritten;
}
while (totalWritten < bufferSize);
或:
//sending response
std::string response = "hardcodedResponse";
const char *buffer = response.c_str();
size_t bufferSize = response.size() + 1; // +1 for the trailing zero
size_t totalWritten = 0;
ssize_t bytesWritten;
do
{
bytesWritten = ::write(socketfd, buffer, bufferSize);
if (bytesWritten <= 0)
{
// handle error...
break;
}
buffer += bytesWritten;
bufferSize -= bytesWritten;
}
while (bufferSize > 0);