博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
php主机字节序和网络字节序
阅读量:4121 次
发布时间:2019-05-25

本文共 2994 字,大约阅读时间需要 9 分钟。

使用php编写socket程序时,也需要注意主机字节序和网络字节序的转换

主机字节序就是我们平常说的大端和小端模式:不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序 这个叫做主机序。Big-Endian和Little-Endian。引用标准的Big-Endian和Little-Endian的定义如下:

  a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
  b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

例子:在内存中双字0x01020304(DWORD)的存储方式

内存地址
4000 4001 4002 4003
LE 04 03 02 01
BE 01 02 03 04

网络字节顺序是指TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

为了进行转换 bsd socket 提供了转换的函数 有下面四个

  htons 把 unsigned short 类型从主机序转换到网络序
  htonl 把 unsigned long 类型从主机序转换到网络序
  ntohs 把 unsigned short 类型从网络序转换到主机序
  ntohl 把 unsigned long 类型从网络序转换到主机序
  在使用 little endian 的系统中 这些函数会把字节序进行转换
  在使用 big endian 类型的系统中 这些函数会定义成空宏
注意:
  1 、网络与主机字节转换函数 :htons ntohs htonl ntohl (s 就是 short l 是 long h 是 host n 是 network)
  2 、不同的 CPU 上运行不同的操作系统,字节序也是不同的

在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.

PHP中并没提供htons,htonl功能的函数,在进行网络通信时,可以通过

string pack ( string $format [, mixed $args [, mixed $... ]] )

array unpack ( string $format , string $data )

进行编解码

其中,format 可以取下面的值:

Code     Description

a     NUL-padded string
A     SPACE-padded string
h     Hex string, low nibble first
H     Hex string, high nibble first
c     signed char
C     unsigned char
s     signed short (always 16 bit, machine byte order)
S     unsigned short (always 16 bit, machine byte order)
n     unsigned short (always 16 bit, big endian byte order)
v     unsigned short (always 16 bit, little endian byte order)
i     signed integer (machine dependent size and byte order)
I     unsigned integer (machine dependent size and byte order)
l     signed long (always 32 bit, machine byte order)
L     unsigned long (always 32 bit, machine byte order)
N     unsigned long (always 32 bit, big endian byte order)
V     unsigned long (always 32 bit, little endian byte order)
f     float (machine dependent size and representation)
d     double (machine dependent size and representation)
x     NUL byte
X     Back up one byte
Z     NUL-padded string (new in PHP 5.5)
@     NUL-fill to absolute position

网络通信

比如现在要通过PHP发送数据包到服务器来登录。在仅需要提供用户名(最多30个字节)和密码(md5之后固定为32字节)的情况下,可以构造如下数据包(当然这事先需要跟服务器协商好数据包的规范,本例以网络字节序通信):
包结构:

字段  字节数 说明

包头  定长         每一个通信消息必须包含的内容
包体  不定长 根据每个通信消息的不同产生变化

其中包头详细内容如下:

字段               字节数 类型       说明

pkg_len         2     ushort     整个包的长度,不超过4K
version         1     uchar     通讯协议版本号
command_id 2     ushort     消息命令ID
result         2     short     请求时不起作用;请求返回时使用

当然实际中可能会涉及到各种校验。本文为了简单,只是列举一下通常的工作流程及处理的方式。

登录(执行命储1001)

字段       字节数 类型         说明

用户名 30     uchar[30] 登录用户名
密码         32     uchar[32] 登录密码

包头是定长的,通过计算可知包头占7个字节,并且包头在包体之前。比如用户陈一回需要登录,密码是123456,则代码如下:

<?php

$version    = 1;
$result     = 0;
$command_id = 1001;
$username   = "陈一回";
$password   = md5("123456");
// 构造包体
$bin_body   = pack("a30a32", $username, $password);
// 包体长度
$body_len   = strlen($bin_body);
$bin_head   = pack("nCns", $body_len, $version, $command_id, $result); //result为什么使用了主机字节序
$bin_data   = $bin_head . $bin_body;
// 发送数据
// socket_write($socket, $bin_data, strlen($bin_data));
// socket_close($socket);

转自:http://www.kongqingquan.com/archives/24

参考:http://www.cnblogs.com/andydao/p/4200662.html

你可能感兴趣的文章
XHProf-php轻量级的性能分析工具
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
OpenCV meanshift目标跟踪总结
查看>>
就在昨天,全球 42 亿 IPv4 地址宣告耗尽!
查看>>
听说玩这些游戏能提升编程能力?
查看>>
如果你还不了解 RTC,那我强烈建议你看看这个!
查看>>
沙雕程序员在无聊的时候,都搞出了哪些好玩的小玩意...
查看>>
Mysql复制表以及复制数据库
查看>>
Linux下SVN客户端使用教程
查看>>
Linux分区方案
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>
OpenFeign学习(三):OpenFeign配置生成代理对象
查看>>
OpenFeign学习(四):OpenFeign的方法同步请求执行
查看>>
OpenFeign学习(五):OpenFeign请求结果处理及重试控制
查看>>
OpenFeign学习(六):OpenFign进行表单提交参数或传输文件
查看>>
Ribbon 学习(二):Spring Cloud Ribbon 加载配置原理
查看>>
Ribbon 学习(三):RestTemplate 请求负载流程解析
查看>>
深入理解HashMap
查看>>