【发布时间】:2018-05-23 00:30:29
【问题描述】:
我正在尝试与我安装的服务器程序通信。服务器以构造数据包的形式发送和接收所有数据,这些数据包遵循以下设置: int int int string nullbyte 像这样:
little endian signed int -> ID 的大小(4 字节)+ Type 的大小(4 字节)+ Body 的大小(空终止符最小为 1)+ 最小为 10 的空字节作为值;
little endian signed int -> id
little endian signed int -> 数据包类型
以空结尾的 ascii 字符串 -> 正文
空字节
我已经设法很好地读取了数据包,但是当我尝试使用密码发送数据包时,服务器完全忽略它,这意味着数据包在某种程度上是错误的。我这样构造数据包:
void Packet::build(){
/*
* Create unsigned char vector to store
* the data while we build the byte array
* and create a pointer so the byte array can
* be modified by the required functions.
*/
std::vector<unsigned char> packet(m_size);
unsigned char *ptr = packet.data();
/*
* Convert each of the three integers as well
* as the string into bytes which will be stored
* back into the memory that ptr points to.
*
* Packet data follows format:
* int32 -> Size of ID + Server Data + body (minimum of 10).
* int32 -> ID of request. Used to match to response.
* int32 -> Server Data type. Identifies type of request.
* String -> Minimum of 1 byte for null terminator.
* String -> Null terminator.
*/
storeInt32Le(ptr, m_sizeInPacket);
storeInt32Le(ptr, m_requestID);
storeInt32Le(ptr, m_serverData);
storeStringNt(ptr, m_body);
/*
* Store the vector in member variable m_cmdBytes;
*
*/
m_cmdBytes = packet;
}
storeInt32Le:
void Packet::storeInt32Le(unsigned char* &buffer, int32_t value) {
/*
* Copy the integer to a byte array using
* bitwise AND with mask to ensure the right
* bits are copied to each segment then
* increment the pointer by 4 for the next
* iteration.
*/
buffer[0] = value & 0xFF;
buffer[1] = (value >> 8) & 0xFF;
buffer[2] = (value >> 16) & 0xFF;
buffer[3] = (value >> 24) & 0xFF;
buffer += 4;
}
storeStringNt:
void Packet::storeStringNt(unsigned char* &buffer, const string &s) {
/*
* Get the size of the string to be copied
* then do a memcpy of string char array to
* the buffer.
*/
size_t size = s.size() + 1;
memcpy(buffer, s.c_str(), size);
buffer += size;
}
最后,我发送它:
bool Connection::sendCmd(Packet packet) {
unsigned char *pBytes = packet.bytes().data();
size_t size = packet.size();
while (size > 0){
int val = send(m_socket, pBytes, size, 0);
if (val <= 0) {
return false;
}
pBytes += val;
size -= val;
}
return true;
}
Packet::bytes() 只返回 m_cmdBytes
【问题讨论】:
-
你需要检查
val是否>0但packet.size();它可能不会一次性发送所有数据。您可能希望使用调试器(或日志记录)在发送之前查看您的数据包是否正确,这样您就可以查看问题是构造还是传输。 (或者甚至使用 wireshark 来查看正在发送的确切内容。) -
你的 memcpy 调用错误:cplusplus.com/reference/cstring/memcpy 对了,你为什么不直接把字节复制到
packet? -
我为 val == packet.size() 添加了一个小检查,它输出到控制台,说明整个数据包已发送并且正在响应。
-
@AlexisShepard David 的观点是您声明整数在协议中定义为小端,但您没有尝试确保整数以小端形式发送。
-
如果您的平台的下一个版本使用超过四个字节来存储整数怎么办?如果它以小端以外的某种形式存储整数怎么办?您正在对您的平台进行代码假设。除非你有充分的理由这样做,否则不要这样做。不这样做很容易。