【问题标题】:network byte order to host byte order conversion in phpphp中网络字节顺序到主机字节顺序转换
【发布时间】:2015-01-03 07:23:44
【问题描述】:

我需要开发一个 PHP 服务器套接字和一个 C 客户端套接字,反之亦然。

我对 C 语言中的 TCP 套接字及其概念非常了解。

我被困在最后一件事上。

我可以从 C 客户端套接字发送整个结构如下

typedef struct _test {
char str[32];
char c;
int i;
float f;
}test;

//Some Coding ...

memset(&t,'\0',sizeof(test));

strcpy(t.str,"Sunny"); //String
t.c = 'M'; //Char
t.i = 26; //Integer
t.f = 98.8; //Float

//Send test STRUCT to server
if(send(sockfd,(void *)&t,sizeof(t),0) < 0)  
{   
    perror("Send failed ");
    exit(0);
}

//一些编码...

我在 PHP 服务器套接字上接收到这个结构如下

...

 $client = socket_accept($socket);

   $input = socket_read($client, 1024);

   $arr = unpack("Z32Str/a1Chr/iInt/fFlt", $input);

   echo $arr['Str']; //Print String

   echo $arr['Chr']; //Print Char

   echo $arr['Int']; //Print Int

   echo $arr['Flt']; //Print Float

...

我正在正确获取字符串和字符,但没有正确获取整数和浮点数,我确信它的网络托管字节顺序(小端序,大端序)问题。

即我得到整数 value436207616

谁能告诉我如何在 PHP 中实现与 ntohl 和 ntohs 等效的功能。


附: :- 我是 PHP 新手...请帮助

【问题讨论】:

  • 问题很可能不是字节顺序,而是结构填充。请记住,大多数 C 编译器填充它们的结构,以便字段从偶数地址开始。在结构中的字符之后,很可能有一个您在 PHP 代码中未处理的 3 字节填充字段。您可以通过在 C 源代码中打印 sizeof(struct _test) 来轻松验证这一点,我敢打赌它是 44 而不是 41。
  • ya joachim,没错...我正在进一步检查...但是您能否建议如何在 PHP 中为此类情况编写解包函数,就像 php 中的新手一样。
  • 大多数编译器支持结构的打包,以最小化填充或完全删除它。在 PHP 中解包时,您可以使用填充,但在 'Chr' 之后添加三个虚拟字节。请注意,更改结构会更改填充。
  • 添加到 Joachim,我会在应用程序启动时将空结构的大小发送到服务器,这样您就可以确定它是您在 PHP 端所期望的。
  • 您可以强制编译器不添加填充,也可以按以下顺序重新组织结构:str、i、f、c

标签: php c


【解决方案1】:

我已经禁用了 C 中的结构填充,如下所示,它起作用了.....

如何禁用结构填充?如下 .... 以下是在 C 中使用 pragma 禁用结构填充的方法。

#pragma pack(push, 1)
//Define your structure here
#pragma pack(pop)
//Structure padding is re enabled.


#pragma pack(push,1)
typedef struct _test {
    char str[32];
    char c;
    int i;
    float f;
}test;
#pragma pack(pop)

或者:

我一直在 C 中进行填充并在 php 端进行以下操作,并且它有效....

$arr = unpack("Z32Str/z4Chr/iInt/fFlt", $input);

【讨论】:

  • 在 gcc 和 clang 中的首选方法是使用 __attribute__((packed)) 而不是 pragma。
  • 是的,我也同意@dho ...看到这篇文章stackoverflow.com/questions/11770451/…
  • 不要使用 $input = trim($input);在 unpack 方法之前的 php 代码中,因为此方法将从字符串的开头和结尾去除空格(或其他字符),这将使二进制字符串对于任何 unpack 方法都不可读.....
  • trim 将去掉一个普通空格、一个制表符、一个新行(换行)、一个回车、NUL 字节和一个垂直制表符......
  • 哇,有人降低了我的声望点。呵呵,真好笑。
猜你喜欢
  • 1970-01-01
  • 2022-01-22
  • 2013-10-23
  • 2015-06-28
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2014-05-18
相关资源
最近更新 更多