【问题标题】:Write and read, socket AF_UNIX in C写入和读取,C 中的套接字 AF_UNIX
【发布时间】:2013-05-06 14:39:54
【问题描述】:

我正在用 C 语言编写一些套接字函数,但遇到了这个问题。 我有一个包含三个字段的结构:

typedef struct {
  char type;           
  unsigned int length; 
  char *buffer;        
} message_t;

我需要包装在相同的字符串(类型、长度、缓冲区)中,然后以原子方式将其写入套接字中。之后使用 read 函数,我需要读取消息并将三个字段插入同一个结构中。我不明白如何将 int 转换为固定长度的字符串。

【问题讨论】:

  • 你想做一些serialization。您可以使用二进制数据格式(例如 XDR 等...)或使用文本格式(JSON、YAML、XML 等...)...
  • 为什么要将 int 转换为字符串?只需将结构写入您的套接字即可。因为你是 AF_UNIX,所以你在同一台机器上,这简化了事情。
  • 这是一个大学项目,我无法更改具体内容。
  • @mah: 如果消息接收端的机器是 SPARC 或 PowerPC 机器,但发送端的机器是 Intel 机器,那么只需将结构写入套接字流即可导致误解,因为发送方是小端机器,接收方是大端机器,unsigned int 中的字节顺序会有所不同。此外,结构中有填充字节,结构中指针的地址在接收机器上是没有意义的(不管字节序)。你必须复制指向的数据!
  • @mah:只有在写入日期的进程读取日期时,才向套接字写入指针(在本例中为 char * buffer)才有意义。

标签: c sockets system-calls


【解决方案1】:

使用 memcpy 将您的结构复制到一个 void 内存块中,该内存块可以解释为字符串或任何您喜欢的内容,将其发送到远程进程,将其类型转换为您的本地结构,您的值应该按照您的意愿恢复。 例如

message_t my_msg;
char out_buf[MAX_LEN] = {0,};

memcpy(out_buf, my_msg, sizeof(message_t));

send_it_over_socket(out_buf);

【讨论】:

    【解决方案2】:

    就是这个思路,虽然我没有测试过,但是我用的很相似。

    首先你需要在两边打包结构:

    #pragma pack(1)
    typedef struct {
       char type;
       unsigned int length;
       char *buffer;
    } message_t;
    

    要发送数据包,请使用如下函数:

    void SendData(char type, unsigned int length, char *data) {
       message_t packet;
    
       packet.type = type;
       // convert the int to network byte order
       packet.length = htonl(length);
    
       // Here we have two options to send the packet:
       // 1 with malloc and one send
           packet.buffer = malloc(length);
           memcpy(packet.buffer, data, length);
           length +=sizeof(char);
           length +=sizeof(int);
           // send it in one shut
           send(mySocket, (const char *)&packet, length, 0);
           // release the memory
           free(packet.buffer);
    
       // 2 without malloc and two sends:
           send(mySocket, (const char *)&packet, sizeof(char)+sizeof(int), 0);
           send(mySocket, data, length, 0);
    }
    

    要读取另一侧的数据,请使用如下方式:

    BOOL RecvData(message_t *packet) {
       // NOTE: 
       // if packet.buffer is not NULL, the caller of this function must 
       // release the memory allocate here
       packet->buffer = NULL;
    
       // at the receiver, you need 2 reads:
       // 1 to know how many bytes to read
       // 2 to read those bytes.
       if (recv(mySocket, (char *)packet, sizeof(char)+sizeof(int), 0) > 0)
       {
           // convert the int to host byte order
           packet->length = ntohl(packet->length);
           packet->buffer=malloc(packet->length);
           // if we got the memory, go ahead
           if (packet->buffer != null)
           {
               if (recv(mySocket, packet->buffer, packet->length, 0) == packet->length)
                   return TRUE;
           }
       }
       return FALSE;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 2022-01-25
      相关资源
      最近更新 更多