如果调用服务端的 Socket?

2017-10-09 09:46:46 +08:00
 xoxo419

公司要做一个扫码开箱的盖. 项目是外包出去的 硬件设备, 服务端, APP 都是外包做的. 我自己是做 PHP 的 然后公司现在又想加一个微信端的[我自己准备用小程序来实现].

现在他们的接口是用 socket[TCP]来做的, 我之前写接口都是 HTTP. 所以不太懂 socket. 看的那是一头雾水.

现在外包那就只给了一份《协议文档》, 没有 PHP 的示例, 求示例.

2313 次点击
所在节点    问与答
16 条回复
xoxo419
2017-10-09 09:47:31 +08:00
lean
2017-10-09 10:20:05 +08:00
在你们的服务器对接微信,然后用微信的信息,根据协议文档 php tcp 对接你们的设备
qiayue
2017-10-09 10:31:43 +08:00
php 用 swoole 来起 socket 服务。
如果 php 只是当做客户端,连接对方 socket 服务,则最简单的方式是用 fsockopen,然后 fwrite,fclose 就可以了。

具体怎么发,给你个原理展示:
$str = '00 01 02 03 04';//字符串形式的十六进制数据
$arr = str_split(str_ireplace(' ', '', $cmd_str), 2);//去掉空格后,2 字符一段切分成数组
$byte_arr = array();
foreach ($arr as $h) {
~~~~$byte_arr[] = chr(hexdec($h));
}
$byte_str = implode('', $byte_arr);
$fp = fsockopen($host, $port, $errno, $errstr, 5);
fwrite($fp, $byte_str);
fclose($fp);
qiayue
2017-10-09 10:32:40 +08:00
勘误,第二行代码有个变量名写错了
$arr = str_split(str_ireplace(' ', '', $str), 2);//去掉空格后,2 字符一段切分成数组
qooweds
2017-10-09 10:49:26 +08:00
第 0 个字节放魔数,第 1 个字节放消息类型,依此类推
不过消息头和消息体没明白什么意思,消息头放 TCP 头里?感觉不太像啊
xoxo419
2017-10-09 11:10:54 +08:00
@qiayue
@qooweds 那这个设备 ID 怎么传呢?
qooweds
2017-10-09 11:24:34 +08:00
@xoxo419 应该是 string 转成字节数组吧?
xoxo419
2017-10-09 11:29:20 +08:00
@qiayue
@qooweds 我也不太清楚..... 上面的 4-7 还有<固定的东西作为头部><变动的东西作为体> 是什么东东, 没有相关的资料可以参考下 ? 搜索都不知道是不是. 上面的表是一个 TCP 的一条数据?
xoxo419
2017-10-09 11:36:02 +08:00
网上找的一段 socket 客户端连接方式. [转自]( http://www.cnblogs.com/kravis/p/5707898.html)
```
<?php
error_reporting(E_ALL);
set_time_limit(0);


$ip = '127.0.0.1';
$port = 8888;

// 1. 创建
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if( $socket == FALSE ) {
echo 'create fail: ' . socket_strerror(socket_last_error());
} else {
echo 'OK';
}

// 2. 链接
echo 'we will try to connect ' . $ip .':' . $port . '\r\n----';
$result = socket_connect($socket, $ip, $port);
if ( $result == FALSE) {

}

$in = 'HO ';
$in .= 'first blood--------';
$out = '';

// 3. 向服务端写入
if( !socket_write($socket, $in, strlen($in)) ) {
echo 'write fail: ' . socket_strerror(socket_last_error());
} else {
echo '-----send to server succefully! \r\n----';
echo 'the content is ' . $in;
}

// 3. 从服务端读取
while ( $out = socket_read($socket, 8129) ) {
echo '-----receive from server succefully!\r\n------';
echo 'the contents is ' . $out;
}

// 4. 关闭
echo '----close socket ...';
socket_close($socket);
echo 'closed ok.';
```

但这个并没有像上面图片那样分段的, 服务端怎么知道我发送的是设备 ID?
qiayue
2017-10-09 11:45:11 +08:00
所有数据都是十六进制拼接在一起的
每一个字节占 2 位
图片中括号里边的数字表示这个数据占几个字节
帧头 1 字节
消息类型 1 字节
长度 2 字节
设备 ID 4 字节

这样从开头数起,设备 ID 就是在第 4~7 字节(从 0 开始)
qiayue
2017-10-09 11:49:55 +08:00
ws 是 websocket 的协议
wss 与 ws 类似于 https 与 http 的关系
小程序用的话,你就要在服务器里搞一个 websocket 服务来做代理了
xoxo419
2017-10-09 13:32:14 +08:00
@qiayue #11 我用 php 去调用, 然后把这段写成 API, 这种方式不行么?
xoxo419
2017-10-09 14:59:38 +08:00
@xoxo419 #9

```
$in = 'HO ';
$in .= 'first blood--------';
$out = '';
```

#9 代码中为什么$in 不直接写要分开两段?
xoxo419
2017-10-09 15:39:46 +08:00
@qiayue #10 这个没看懂.

我找到一份 JAVA 的,
```

public String toString() {
return "NettyMessage{" +
"magic=" + magic +
", msgType=" + msgType +
", reserve=" + reserve +
", devId=" + devId +
", can1=" + can1 +
", can2=" + can2 +
", can3=" + can3 +
", can3_num=" + can3_num +
", rt=" + rt +
'}';
}
```

```
SocketService.client.writeAndFlush(builder.build());
```

这种是什么格式? PHP 如何可以转成这样的格式?
mengzhuo
2017-10-09 16:41:00 +08:00
这个文档不标准啊,
各个数据必须标注类型和长度,而且用个 excel 写……我也是醉了
xoxo419
2017-10-17 08:37:37 +08:00
@qiayue 代理服务器, 需要 nginx 配合么, 还是搭建一 websocket 服务器? 找了很多资料也没有找到配置的方法.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/396063

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX