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

问题描述:

当与外部系统通信时,他们希望我在响应结束时添加空字节。不过我现在面临的一些问题:字符数组中的十六进制在写入套接字时产生随机字符

//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 

您为空,而不是两个做一个额外的字符,这样就把空在最后无法超越结束。

buffer[bufferSize-1] = 0x00; 
+0

妈的,我是如此专注于六角形/插座部分,我完全没有看到这一点。谢谢 :) – Aelion

首先,您正在依赖称为“可变长度阵列”的非标准功能。只有少数C++编译器支持VLA,然后才作为可选的扩展。您应该使用STL std::vector容器代替动态大小的数组。

但是,更重要的是,您正在将空字节写入错误的数组索引。 buffer[]的有效索引范围是0..bufferSize-1。写入buffer[bufferSize]将不会在数据末尾的正确位置追加空终止符,并且它会清除周围的内存。

您需要更改此:

buffer[bufferSize] = 0x00; 

要这样:

buffer[bufferSize-1] = 0x00; 

您还没有正确管理调用write(),无论是。特别是,它可以返回-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);