字符数组中的十六进制在写入套接字时导致随机字符

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);