【发布时间】:2016-08-02 18:16:04
【问题描述】:
我在发送数据时遇到了 winsock 客户端-服务器问题。我有一个包含用户名作为主键的地图,以及每个用户的消息向量(存储在结构中):
map<std::string,std::vector<message *> > data;
struct message{
static unsigned int last_id;
unsigned int id;
std::string baa;
std::string timestamp;
}
我还有一个序列化程序,以便通过 Winsock 将其发送到客户端(只接受字符数组)
class MessageSerializer
{
public:
MessageSerializer(const message& messageStruct)
: m_msgRef(messageStruct)
, m_msgLength(m_msgRef.msg.length())
, m_timeLength(m_msgRef.timestamp.length())
{}
size_t RequiredBufferSize() const
{
return sizeof(int) + sizeof(size_t)*2 + m_msgLength + m_timeLength;
}
void Serialize(void* buffer) const
{
PushNum (buffer, m_msgRef.id);
PushString (buffer, m_msgRef.msg.c_str(), m_msgLength);
PushString (buffer, m_msgRef.timestamp.c_str(), m_timeLength);
}
private:
const message& m_msgRef;
const size_t m_msgLength;
const size_t m_timeLength;
template<typename INTEGER>
void PushNum(void*& buffer, INTEGER num) const
{
INTEGER* ptr = static_cast<INTEGER*>(buffer);
//copying content
*ptr = num;
//updating the buffer pointer to point the next position to copy
buffer = ++ptr;
}
void PushString(void*& buffer, const char* cstr, size_t length) const
{
PushNum(buffer, length);
//copying string content
memcpy(buffer, cstr, length);
//updating the buffer pointer to point the next position to copy
char* ptr = static_cast<char*>(buffer);
ptr += length;
buffer = ptr;
}
}
为了实现这个序列化程序,我做了以下工作:
message msg_cpy=*data[recvbuf_usrn].at(0);
MessageSerializer serializer(msg_cpy);
char* buffer = new char[serializer.RequiredBufferSize()];
serializer.Serialize(buffer);
发送时间戳时出现问题。在msg_cpy 中,我正确存储了数据(例如 id=1,msg=hello,timestamp=2016-04-02 10:40:45),但是在发送数据时,时间戳只保存前三个值,即也就是说,在客户端,我反序列化后收到id=1,msg=hello,timestamp=201后跟垃圾。我知道问题出在服务器上,我推断它可能是序列化功能(唯一的其他选择可能是 Winsock 的“发送”功能)。但它有什么问题呢?如果我写一个 msg=2016-04-02 10:40:20,我会在客户端收到。
感谢任何帮助
【问题讨论】:
-
你应该尝试建立一个minimal reproducible example。问题可能在于您使用序列化器发送数据的方式,即未显示的代码(我的水晶球目前无法使用......)
-
发送数据我发送从
serializer.Serialize(buffer)返回的buffer,因为发送的Winsock函数只允许字符数组。 link 在这个网页中出现了 Winsock 的发送函数,它将recvbuf作为输入数据,在我的例子中,它是缓冲区。但我认为问题出在序列化时,缓冲区已经在时间戳部分占用了垃圾。这就是为什么我没有附上其余的。如果您知道为什么会发生这种情况,我将不胜感激。不管怎么说,还是要谢谢你! @serge-ballesta -
这只是一个疯狂的预感,因为您没有包含发送/接收代码:TCP 是一个面向流的协议;单个
recv()可能不会返回所有数据。您需要循环调用recv(),直到收到完整的“消息”。 -
Yoy 是对的@keithmo 我认为问题出在序列化上,而我在服务器的发送函数中输入的缓冲区长度总是小于所需的。序列化程序工作正常。
标签: c++ serialization winsock