Socket粘包处理

背景

这段时间刚忙完了一个项目,涉及到PHP与Java进行socket通信的问题,应用场景是PHP端向Java端发送数据,并等待Java的响应结果,数据格式为JSON。

遇到的问题

PHP端发送数据后,Java端从socket里读取数据,但是一直读不到结束符。

原因

PHP需要调用socket_close函数才会向socket里面写入结束符。

改进方法

PHP端与Java端之间确定每次发送数据包的长度,用4个字节表示数据长度,PHP端先发送数据包长度,再发送数据包,Java端先接收4个字节长度的数据包长度,再根据数据包长度接收数据包。PHP端代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$socket = socket_create ( AF_INET, SOCK_STREAM, SOL_TCP  ) or die ( 'could not create socket'  );  
$connect = socket_connect ( $socket, 'xxx.xxx.xxx.xxx', xxxx);
//服务端发送数据
$arr = array("data" => "dadadada");
$strlen = pack('i', strlen(json_encode($arr)));
var_dump($strlen);
socket_write ($socket, $strlen);
socket_write ($socket, json_encode($arr), strlen(json_encode($arr)));
$response = socket_read($socket, 4);
$res = unpack('i', $response);
var_dump($res);
$response = socket_read($socket, $res[1]);
var_dump($response);
socket_close($socket);

packunpack函数使用说明见PHP官方文档