【问题标题】:Sending a C char array over a socket通过套接字发送 C 字符数组
【发布时间】:2011-03-30 08:32:14
【问题描述】:

我想通过 unix 中的 tcp 套接字发送一个字符数组。

我的第一个想法是使用一个普通的 char 数组作为将通过套接字发送的结构:

typedef struct __attribute__((packed))
{
   uint8_t type;
   uint8_t id_index;
   char char_value[STR_MSG_MAX];
} a_msg;

仅仅是因为 C 字符总是 8 位长。然而,经过一番谷歌搜索后,我发现即使一个 char 总是 8 位长,其底层表示实际上也可能是一个 32 位整数。所以我的印象是 char 可能不是在消息中表示字符串的最佳方式,该消息将通过套接字从 FreeBSd 发送到 Linux(或者如果你想输入一些其他 unixes =)...)。

stdint.h 存在于当今所有现代 unix 上(我希望如此),我的想法是,也许 uint8_t 或 int8_t 数组可以解决问题。

typedef struct __attribute__((packed))
{
   uint8_t type;
   uint8_t id_index;
   uint8_t char_value[STR_MSG_MAX];
} a_msg;

typedef struct __attribute__((packed))
{
   uint8_t type;
   uint8_t id_index;
   int8_t char_value[STR_MSG_MAX];
} a_msg;

但是,uint8_t 是无符号字符,而 int8_t 是有符号字符。标准的 C char 既不是这样,因为我理解的实现是未定义的。

我的问题是: 在 C 中表示字符数组(字符串)的最佳方式是什么,它将以 *nix(Linux、FreeBSD 等)平台无关的方式通过 tcp/ip 发送。

【问题讨论】:

  • 发送字符串的最佳方式可能只是发送到write 原始字符串。我猜您想一次性发送您显示的结构,而不仅仅是字符数据?

标签: c unix


【解决方案1】:

你不能说你要寄什么 c。此信息不会被转移。

你所要做的就是:

char* buffer = (char*)(&a_msg);

如果可能,最安全的方法是使用无符号字符。

【讨论】:

  • 好吧,不。然而,这是一个代表数据的回合,所以如果你知道在另一边收到了什么,那就是另一回事了,那么你可以将你的字节流转换成别的东西。
  • 我刚刚意识到,这个问题是关于 char / uchar 在多个平台上的表示。
【解决方案2】:

我个人会选择这样的东西:

typedef struct __attribute__((packed))
{
   uint8_t type;
   uint8_t id_index;
   uint8_t padding[2]; //this is to align to 32bit boundary
   uint8_t char_value[STR_MSG_MAX];
} a_msg;

但它可以在没有填充的情况下工作。

在 C 中,char 总是 8 位长。所以一个 char 数组总是一个字节数组。但是字符文字 'x' 是 32 位。这可以在字符文字上使用sizeof 运算符来验证。您还将看到所有返回单个字符(如getch)的函数都返回int。原因是我们需要一种指示文件结束 EOF 的方法。这只能使用 8 位范围之外的值来完成。

【讨论】:

  • 在常见的现代实践中,char 的长度为 8 位。但这不是标准所要求的——C 可以在 6 位或 16 位处理器上工作。
  • @bstpierre:char 允许的 最小值 为 8 位。因此,6 位处理器必须用 12 位字表示 char,而 C 程序将无法寻址单个 6 位单元。
  • @caf - 你说得对,我在上面打错了一个字符。意思是说 36 或 16。感谢您的更正。
  • 即使填充不是 100% 必要的,它的成本也很低,并且可以简化数组上的基本复制操作。
  • @Codeape:填充和类似的东西并不重要。对于您的其他两个领域来说,使用无符号整数类型确实是一种很好的态度(就像您所做的那样)。对于数据本身,通常将它们视为“未解释”字节,因此char 是一个不错的选择,在这里。
【解决方案3】:

虽然char 可能超过 8 位宽,但它必须始终是(相等)最窄的类型。 (除其他原因外,sizeof(char) 被定义为 1)。

所以如果平台提供int8_t,那么char也必须正好是8位(因为char被单独限制为至少8位)。这意味着您不妨使用char

【讨论】:

  • 如果我从一个 char 由例如 32 位 int 表示的平台发送,而接收端用 8 位数据类型表示一个字符,会发生什么?如果我发送一个 40 个字符的数组,我将发送 40 x 32 位,但接收端会发生什么以 40 x 8 位的结构表示它?
  • @Codeape:当然,这是一个问题——但这不是可以通过使用int8_t 解决的问题,因为具有32 位char 的平台无法提供这种类型。无论如何,此类平台通常没有网络库。
【解决方案4】:

我认为打包结构的想法是要走的路。我会编写一些测试代码以确保它正常工作。执行 sizeof(a_msg) 以查看它的大小。您应该能够判断打包是否有效,而无需通过套接字发送消息。

【讨论】:

  • 好。我正在打包结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 2014-02-09
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
相关资源
最近更新 更多