c - 使用套接字通过 Tcp/IP 发送消息

标签 c sockets tcp struct

我正在尝试在客户端/服务器之间发送数据,数据看起来像

typedef Struct Message 
  { int id;
    int message_length;
     char* message_str;
    }message;

我正在尝试在客户端和服务器之间写入读取此消息,不断更新此结构中的元素。我听说 Writev 可以解决这个问题。我想发送一个 向服务器发送消息,然后服务器提取元素并使用这些元素作为条件来执行正确的方法?

最佳答案

假设您想自己进行序列化,而不是使用 Google Protocol Buffers 或某些库来为您处理它,我建议编写一对如下函数:

// Serializes (msg) into a flat array of bytes, and returns the number of bytes written
// Note that (outBuf) must be big enough to hold any Message you might have, or there will
// be a buffer overrun!  Modifying this function to check for that problem and
// error out instead is left as an exercise for the reader.
int SerializeMessage(const struct Message & msg, char * outBuf)
{
   char * outPtr = outBuf;

   int32_t sendID = htonl(msg.id);   // htonl will make sure it gets sent in big-endian form
   memcpy(outPtr, &sendID, sizeof(sendID));
   outPtr += sizeof(sendID);

   int32_t sendLen = htonl(msg.message_length);
   memcpy(outPtr, &sendLen, sizeof(sendLen));
   outPtr += sizeof(sendLen);

   memcpy(outPtr, msg.message_str, msg.message_length);  // I'm assuming message_length=strlen(message_str)+1 here
   outPtr += msg.message_length;

   return (outPtr-outBuf);
}

// Deserializes a flat array of bytes back into a Message object.  Returns 0 on success, or -1 on failure.
int DeserializeMessage(const char * inBuf, int numBytes, struct Message & msg)
{
   const char * inPtr = inBuf;

   if (numBytes < sizeof(int32_t)) return -1;  // buffer was too short!
   int32_t recvID = ntohl(*((int32_t *)inPtr));
   inPtr += sizeof(int32_t);
   numBytes -= sizeof(int32_t);
   msg.id = recvID;

   if (numBytes < sizeof(int32_t)) return -1;   // buffer was too short!
   int32_t recvLen = ntohl(*((int32_t *)inPtr));
   inPtr += sizeof(int32_t);
   numBytes -= sizeof(int32_t);
   msg.message_length = recvLen;       if (msg.message_length > 1024) return -1;  /* Sanity check, just in case something got munged we don't want to allocate a giant array */

   msg.message_str = new char[msg.message_length];
   memcpy(msg.message_str, inPtr, numBytes);
   return 0;
}

通过这些函数,您现在可以将消息转换为简单的字符数组,然后随意转换回来。因此,现在您所要做的就是通过 TCP 连接发送字符数组,在远端接收它,然后将数组反序列化回消息结构。

与此相关的一个问题是您的 char 数组将是可变长度的(由于存在长度可能不同的字符串),因此您的接收者将需要一些简单的方法来知道在调用 DeserializeMessage 之前要接收多少字节() 在数组上。

处理该问题的一个简单方法是始终先发送 4 字节整数,然后再发送字符数组。 4 字节整数应始终是即将到来的数组的大小(以字节为单位)。 (在发送之前,请务必先通过 htonl() 将整数转换为大端字节序,然后在使用之前通过 htonl() 在接收器上将其转换回 native 字节序)。

关于c - 使用套接字通过 Tcp/IP 发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5759043/

相关文章:

c - 将单词读入结构数组的函数

c - 我的蛇排序算法中的段错误(核心转储)错误

php - PHP SMTP服务器使用套接字: connection refused

node.js - 两个nodejs应用程序之间的通信

sockets - 需要更多关于 listen system call linux 的见解

c - 无论使用什么数据大小进行分配,数组大小都会初始化为 8

c - 在不违反严格的别名规则的情况下处理数据序列化

c - 奇怪的 printf() 行为

java - 在 Java 中检测无法访问的主机的最快方法是什么?

c++ - boost::asio::async_connect 不仅创建了一个 TCP 连接,还创建了两个