当我们需要在不同服务器或者不同的语言之间做数据交换,我们有一种方法是用Socket做数据代理。Socket是源于UNIX的套接字,基于TCP/IP协议,是从UNIX早期的命令集中演化而来的,基础的模式是“连接-读写-关闭”。Socket可以应用于B/S和C/S两种不同的网络软件架构上,现在已经被广泛的引用。
php的Socket模块虽然相对比较简陋,一些复杂的应用会出现一些莫名奇妙的问题,但是单单作为基础的数据代理来讲还是经受了人们的检验。
一、Socket传输的是什么
Socket传输的是字节流,没有定义边界。只是通过调节缓冲区的大小来完成流的截断,当然设置缓冲区的大小都是必须的,否则Socket也许会一直工作下去。Socket传输的数据很容易被截取并且会直接展示出来,所以你通常需要对你的数据进行加密,比如AES,就是很好的加密算法,不要用MD5这样的散列表,否则你会死得很惨。
PHP似乎想要get字节流加上边界,在它的socket_write这个函数中声明的三个参数,它的文档里面说如果你将第三个参数设置为PHP_NORMAL_READ,那么将会读取到/r或者/n,可惜,当我这样做的时候,程序溢出了。原因至今不明。
二、用php做一个SocketServer
我们先抛弃类,这篇将没有一个类定义出现。
前面我们已经说了Socket的工作模式是“连接-读写-关闭”。作为服务器,我们要做的事情是建立一个socket,绑定一个端口,然后监视每一个连接,读取他们传来的消息,并给予他们反馈,然后将这个连接毙掉。现在我们开始

< ?php
//===================
//SockServ.php
//===================
define(’SOCKIP’, ‘localhost’);
define(’SOCKPORT’, ‘12345′);
 
/**
* Set up our socket
*/
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //创建一个socket
printf("Socket created.\r\n");
socket_bind($sock, SOCKIP, SOCKPORT); //绑定一个端口
socket_listen($sock); //开始监视了
printf("Socket has set up.\r\n\r\n");
 
while(true) {
$conn = socket_accept($sock); //抓到一个,允许它的连接
if ($conn) {
printf("==========================================\r\n");
printf("Socket connected.\r\n");
while($data = socket_read($conn, 1024)) {
//千万不能加上PHP_NORMAL_READ啊
$buffer = $data;
printf("Data Received.\r\n");
print_r("Buffer: ".$buffer."\r\n");
socket_write($conn, "OK"); //告诉客户端,OK,我收到了
printf("Successed!\r\n");
}
socket_close($conn); //工作完成,你可以去了
printf("Closed the socket\r\n");
printf("==========================================\r\n\r\n");
}
}
?>

上面这段程序,你最好别用浏览器来跑,你可能会得到一个超时,你应该在命令行里面跑。在服务器上,让它跑在后台,然后就让它呆在那里吧,没事的。
三、还有客户端呢
我们当然还需要一个客户端,不然你执行上面程序时会一直停在“Socket has set up.”。客户端的任务就是在浏览器里打开一张页面程序,向服务器端发送那么一个字符串,然后接受服务器返回的“OK”。我们开始吧

< ?php
//===================
//SockClient.php
//===================
define(’SOCKIP’, ‘localhost’);
define(’SOCKPORT’, ‘12345′);
 
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //创建一个socket
$connStat [...]