本来是搜一些html5 websocket资料看的,结果被引去看了php的socket编程。下面是一些简单的例子,在命令行运行php脚本就行

[命令行运行PHP]PHP中有一个php.exe文件,可以用命令执行PHP脚本。如:D:/php.exe -f F:/test.php ; 可以使用php.exe -h查看更多参数 :

server端:

  1. <?php
  2. /**
  3. * 服务器端代码
  4. *
  5. */
  6. //确保在连接客户端时不会超时
  7. set_time_limit(0);
  8. //设置IP和端口号
  9. $address = "localhost";
  10. $port = 1234; //调试的时候,可以多换端口来测试程序!
  11. //创建一个SOCKET
  12. if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false)
  13. {
  14. echo "socket_create() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n";
  15. die;
  16. }
  17. //阻塞模式
  18. if (socket_set_block($sock) == false)
  19. {
  20. echo "socket_set_block() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n";
  21. die;
  22. }
  23. //绑定到socket端口
  24. if (socket_bind($sock, $address, $port) == false)
  25. {
  26. echo "socket_bind() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n";
  27. die;
  28. }
  29. //开始监听
  30. if (socket_listen($sock, 4) == false)
  31. {
  32. echo "socket_listen() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n";
  33. die;
  34. }
  35. do
  36. {
  37. if (($msgsock = socket_accept($sock)) === false)
  38. {
  39. echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error()) . "/n";
  40. die;
  41. }
  42. //发到客户端
  43. $msg = "welcome /n";
  44. if (socket_write($msgsock, $msg, strlen($msg)) === false)
  45. {
  46. echo "socket_write() failed: reason: " . socket_strerror(socket_last_error()) ."/n";
  47. die;
  48. }
  49. echo "读取客户端发来的信息/n";
  50. $buf = socket_read($msgsock, 8192);
  51. echo "收到的信息: $buf   /n";
  52. socket_close($msgsock);
  53. } while (true);
  54. socket_close($sock);
  55. ?>

client端:

  1. <?php
  2. /**
  3. * 客户端代码
  4. */
  5. error_reporting(0);
  6. set_time_limit(0);
  7. echo " TCP/IP Connection /n";
  8. $service_port = 10001;
  9. $address = '127.0.0.1';
  10. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  11. if ($socket === false)
  12. {
  13. die;
  14. }
  15. else
  16. {
  17. echo "OK";
  18. }
  19. echo "试图连接 ";
  20. if (socket_connect($socket, $address, $service_port) == false)
  21. {
  22. $error = socket_strerror(socket_last_error());
  23. echo "socket_connect() failed./n","Reason: {$error} /n";
  24. die;
  25. }
  26. else
  27. {
  28. echo "连接OK/n";
  29. }
  30. $in   = "Hello World/r/n";
  31. if (socket_write($socket, $in, strlen($in)) === false)
  32. {
  33. echo "socket_write() failed: reason: " . socket_strerror(socket_last_error()) ."/n";
  34. die;
  35. }
  36. else
  37. {
  38. echo "发送到服务器信息成功!/n","发送的内容为: $in  /n";
  39. }
  40. $out  = "";
  41. while ($out = socket_read($socket, 8192))
  42. {
  43. echo "接受的内容为: ".$out;
  44. }
  45. echo "关闭SOCKET…/n";
  46. socket_close($socket);
  47. echo "关闭OK/n";
  48. ?>

再看websocket协议,是HTTP协议升级来的。看其消息头:

所以server端需要解析一下,并返回握手的协议内容:

在网上找到解析的相关代码 phpwebsocket - url:   http://code.google.com/p/phpwebsocket/

  1. // Usage: $master=new WebSocket("localhost",12345);
  2. class WebSocket{
  3. var $master;
  4. var $sockets = array();
  5. var $users   = array();
  6. var $debug   = false;
  7. function __construct($address,$port){
  8. error_reporting(E_ALL);
  9. set_time_limit(0);
  10. ob_implicit_flush();
  11. $this->master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)     or die("socket_create() failed");
  12. socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1)  or die("socket_option() failed");
  13. socket_bind($this->master, $address, $port)                    or die("socket_bind() failed");
  14. socket_listen($this->master,20)                                or die("socket_listen() failed");
  15. $this->sockets[] = $this->master;
  16. $this->say("Server Started : ".date('Y-m-d H:i:s'));
  17. $this->say("Listening on   : ".$address." port ".$port);
  18. $this->say("Master socket  : ".$this->master."/n");
  19. while(true){
  20. $changed = $this->sockets;
  21. socket_select($changed,$write=NULL,$except=NULL,NULL);
  22. foreach($changed as $socket){
  23. if($socket==$this->master){
  24. $client=socket_accept($this->master);
  25. if($client<0){ $this->log("socket_accept() failed"); continue; }
  26. else{ $this->connect($client); }
  27. }
  28. else{
  29. $bytes = @socket_recv($socket,$buffer,2048,0);
  30. if($bytes==0){ $this->disconnect($socket); }
  31. else{
  32. $user = $this->getuserbysocket($socket);
  33. if(!$user->handshake){ $this->dohandshake($user,$buffer); }
  34. else{ $this->process($user,$this->unwrap($buffer)); }
  35. }
  36. }
  37. }
  38. }
  39. }
  40. function process($user,$msg){
  41. /* Extend and modify this method to suit your needs */
  42. /* Basic usage is to echo incoming messages back to client */
  43. $this->send($user->socket,$msg);
  44. }
  45. function send($client,$msg){
  46. $this->say("> ".$msg);
  47. $msg = $this->wrap($msg);
  48. socket_write($client,$msg,strlen($msg));
  49. $this->say("! ".strlen($msg));
  50. }
  51. function connect($socket){
  52. $user = new User();
  53. $user->id = uniqid();
  54. $user->socket = $socket;
  55. array_push($this->users,$user);
  56. array_push($this->sockets,$socket);
  57. $this->log($socket." CONNECTED!");
  58. $this->log(date("d/n/Y ")."at ".date("H:i:s T"));
  59. }
  60. function disconnect($socket){
  61. $found=null;
  62. $n=count($this->users);
  63. for($i=0;$i<$n;$i++){
  64. if($this->users[$i]->socket==$socket){ $found=$i; break; }
  65. }
  66. if(!is_null($found)){ array_splice($this->users,$found,1); }
  67. $index=array_search($socket,$this->sockets);
  68. socket_close($socket);
  69. $this->log($socket." DISCONNECTED!");
  70. if($index>=0){ array_splice($this->sockets,$index,1); }
  71. }
  72. function dohandshake($user,$buffer){
  73. $this->log("/nRequesting handshake...");
  74. $this->log($buffer);
  75. list($resource,$host,$origin,$key1,$key2,$l8b) = $this->getheaders($buffer);
  76. $this->log("Handshaking...");
  77. //$port = explode(":",$host);
  78. //$port = $port[1];
  79. //$this->log($origin."/r/n".$host);
  80. $upgrade  = "HTTP/1.1 101 WebSocket Protocol Handshake/r/n" .
  81. "Upgrade: WebSocket/r/n" .
  82. "Connection: Upgrade/r/n" .
  83. //"WebSocket-Origin: " . $origin . "/r/n" .
  84. //"WebSocket-Location: ws://" . $host . $resource . "/r/n" .
  85. "Sec-WebSocket-Origin: " . $origin . "/r/n" .
  86. "Sec-WebSocket-Location: ws://" . $host . $resource . "/r/n" .
  87. //"Sec-WebSocket-Protocol: icbmgame/r/n" . //Client doesn't send this
  88. "/r/n" .
  89. $this->calcKey($key1,$key2,$l8b) . "/r/n";// .
  90. //"/r/n";
  91. socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0)));
  92. $user->handshake=true;
  93. $this->log($upgrade);
  94. $this->log("Done handshaking...");
  95. return true;
  96. }
  97. function calcKey($key1,$key2,$l8b){
  98. //Get the numbers
  99. preg_match_all('/([/d]+)/', $key1, $key1_num);
  100. preg_match_all('/([/d]+)/', $key2, $key2_num);
  101. //Number crunching [/bad pun]
  102. $this->log("Key1: " . $key1_num = implode($key1_num[0]) );
  103. $this->log("Key2: " . $key2_num = implode($key2_num[0]) );
  104. //Count spaces
  105. preg_match_all('/([ ]+)/', $key1, $key1_spc);
  106. preg_match_all('/([ ]+)/', $key2, $key2_spc);
  107. //How many spaces did it find?
  108. $this->log("Key1 Spaces: " . $key1_spc = strlen(implode($key1_spc[0])) );
  109. $this->log("Key2 Spaces: " . $key2_spc = strlen(implode($key2_spc[0])) );
  110. if($key1_spc==0|$key2_spc==0){ $this->log("Invalid key");return; }
  111. //Some math
  112. $key1_sec = pack("N",$key1_num / $key1_spc); //Get the 32bit secret key, minus the other thing
  113. $key2_sec = pack("N",$key2_num / $key2_spc);
  114. //This needs checking, I'm not completely sure it should be a binary string
  115. return md5($key1_sec.$key2_sec.$l8b,1); //The result, I think
  116. }
  117. function getheaders($req){
  118. $r=$h=$o=null;
  119. if(preg_match("/GET (.*) HTTP/"               ,$req,$match)){ $r=$match[1]; }
  120. if(preg_match("/Host: (.*)/r/n/"              ,$req,$match)){ $h=$match[1]; }
  121. if(preg_match("/Origin: (.*)/r/n/"            ,$req,$match)){ $o=$match[1]; }
  122. if(preg_match("/Sec-WebSocket-Key1: (.*)/r/n/",$req,$match)){ $this->log("Sec Key1: ".$sk1=$match[1]); }
  123. if(preg_match("/Sec-WebSocket-Key2: (.*)/r/n/",$req,$match)){ $this->log("Sec Key2: ".$sk2=$match[1]); }
  124. if($match=substr($req,-8))                                                                  { $this->log("Last 8 bytes: ".$l8b=$match); }
  125. return array($r,$h,$o,$sk1,$sk2,$l8b);
  126. }
  127. function getuserbysocket($socket){
  128. $found=null;
  129. foreach($this->users as $user){
  130. if($user->socket==$socket){ $found=$user; break; }
  131. }
  132. return $found;
  133. }
  134. function     say($msg=""){ echo $msg."/n"; }
  135. function     log($msg=""){ if($this->debug){ echo $msg."/n"; } }
  136. function    wrap($msg=""){ return chr(0).$msg.chr(255); }
  137. function  unwrap($msg=""){ return substr($msg,1,strlen($msg)-2); }
  138. }
  139. class User{
  140. var $id;
  141. var $socket;
  142. var $handshake;
  143. }

继承类:可以自己按需写,这里我添加了几行代码,sendAll()等,很方便就改成了一个即时的网页版聊天室。

  1. // Run from command prompt > php -q chatbot.demo.php
  2. include "websocket.class.php";
  3. // Extended basic WebSocket as ChatBot
  4. class ChatBot extends WebSocket{
  5. function process($user,$msg){
  6. if (isset($user->first)) {
  7. $this->send($user->socket,'');
  8. $user->first = true;
  9. }
  10. $this->say("< ".$msg);
  11. switch($msg){
  12. case "hello" : $this->send($user->socket,"hello human");                       break;
  13. case "hi"    : $this->send($user->socket,"zup human");                         break;
  14. case "name"  : $this->send($user->socket,"my name is Multivac, silly I know"); break;
  15. case "age"   : $this->send($user->socket,"I am older than time itself");       break;
  16. case "date"  : $this->send($user->socket,"today is ".date("Y.m.d"));           break;
  17. case "time"  : $this->send($user->socket,"server time is ".date("H:i:s"));     break;
  18. case "thanks": $this->send($user->socket,"you're welcome");                    break;
  19. case "bye"   : $this->send($user->socket,"bye");                               break;
  20. //default      : $this->send($user->socket,$msg." not understood");              break;
  21. default      : $this->sendAll($user, $msg);              break;
  22. }
  23. }
  24. function sendAll($currentUser, $msg){
  25. $usersList = $this->users;
  26. foreach ($usersList as $user){
  27. if ($user !== $currentUser) // 自己发送的消息就不再接收一次了
  28. $this->send($user->socket, $msg);
  29. }
  30. }
  31. }
  32. $master = new ChatBot("localhost",12345);

客户端代码:

<html>

<head>

<title>WebSocket</title>

<style>

html,body{font:normal 0.9em arial,helvetica;}

#log {width:440px; height:200px; border:1px solid #7F9DB9; overflow:auto;}

#msg {width:330px;}

</style>

<script>

var socket;

function init(){

var host = "ws://localhost:12345/websocket/server.php";

try{

socket = new WebSocket(host);

log('WebSocket - status '+socket.readyState);

socket.onopen    = function(msg){ log("Welcome - status "+this.readyState); };

socket.onmessage = function(msg){ log("Received: "+msg.data); };

socket.onclose   = function(msg){ log("Disconnected - status "+this.readyState); };

}

catch(ex){ log(ex); }

$("msg").focus();

}

function send(){

var txt,msg;

txt = $("msg");

msg = txt.value;

if(!msg){ alert("Message can not be empty"); return; }

txt.value="";

txt.focus();

try{ socket.send(msg); log('Sent: '+msg); } catch(ex){ log(ex); }

}

function quit(){

log("Goodbye!");

socket.close();

socket=null;

}

// Utilities

function $(id){ return document.getElementById(id); }

function log(msg){ $("log").innerHTML+="<br>"+msg; }

function onkey(event){ if(event.keyCode==13){ send(); } }

</script>

</head>

<body onload="init()">

<h3>WebSocket v2.00</h3>

<div id="log"></div>

<input id="msg" type="textbox" onkeypress="onkey(event)"/>

<button onclick="send()">Send</button>

<button onclick="quit()">Quit</button>

<div>Commands: hello, hi, name, age, date, time, thanks, bye</div>

</body>

</html>

PS:

*  这个websocket的类文件可能有一点问题,客户端握手后应该接收的第一条信息都丢失了,没细看代码,以后再检查吧。

Websocket和PHP Socket编程的更多相关文章

  1. C# socket编程实践——支持广播的简单socket服务器

    在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/clie ...

  2. 基于libevent, libuv和android Looper不断演进socket编程 - 走向架构师之路 - 博客频道 - CSDN.NET

    基于libevent, libuv和android Looper不断演进socket编程 - 走向架构师之路 - 博客频道 - CSDN.NET 基于libevent, libuv和android L ...

  3. C# socket编程实践

    C# socket编程实践——支持广播的简单socket服务器   在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# ...

  4. PHP Socket 编程进阶指南

    学习准备 Linux 或者 Mac 环境: 安装有 Sockets 扩展: 了解 TCP/IP 协议. socket函数只是PHP扩展的一部分,编译PHP时必须在配置中添加 --enable-sock ...

  5. 转 网络编程学习笔记一:Socket编程

    题外话 前几天和朋友聊天,朋友问我怎么最近不写博客了,一个是因为最近在忙着公司使用的一些控件的开发,浏览器兼容性搞死人:但主要是因为这段时间一直在看html5的东西,看到web socket时觉得很有 ...

  6. 老雷socket编程之认识常用协议

    老雷socket编程之常见网络协议 1.ip IP协议是将多个包交换网络连接起来,它在源地址和目的地址之间传送一种称之为数据包的东西, 它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求. ...

  7. Linux下的C Socket编程 -- server端的继续研究

    Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...

  8. Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!

    随着HTML5 WebSocket技术的日益成熟与普及,我们可以借助WebSocket来更加方便地打通BS与CS -- 因为B/S中的WebSocket可以直接连接到C/S的服务端,并进行双向通信.如 ...

  9. java socket编程(li)

    一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以 ...

随机推荐

  1. 多线程学习之AsyncOperation实现线程间交互

    1.首先我们要实现如下图的效果:                                                          a.主线程A运行方法段1时创建子线程B b.然后子线 ...

  2. C# XML - XmlNode and XmlAttribute

    public static string TestXML(string path) { XmlDocument doc = new XmlDocument(); doc.Load(path); Xml ...

  3. Codeforces Round #360 (Div. 2) D. Remainders Game 中国剩余定理

    题目链接: 题目 D. Remainders Game time limit per test 1 second memory limit per test 256 megabytes 问题描述 To ...

  4. BZOJ 3436: 小K的农场 差分约束

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3436 题解: 裸的差分约束: 1.a>=b+c  ->  b<=a-c ...

  5. 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

    // ConsoleApplication2.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "stdafx.h ...

  6. ios开发之数据存取1-SQLite

    iOS开发中常用的数据存取方式有: XML属性列表-PList NSKeyedArchiver 归档 Preference-偏好设置 SQLite3 Core Data-以面向对象的方式操作数据库SQ ...

  7. 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态

    以下属于不明来源资料: 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根 ...

  8. Properties --- C++读配置信息的类(一)

    http://blog.csdn.net/billow_zhang/article/details/4304980 在开发实践中,积累了一些通用的C++ 类库,在此写出来给大家分享.也希望能给出更好的 ...

  9. WCF入门(七)——异常处理1

    首先以一个简单的例子演示一下远程调用发生异常的结果: 服务器端代码如下: [ServiceContract] public interface IService1 { [OperationContra ...

  10. SDUT1061Binomial Showdown(组合数)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1061 题意 : 表示这个题的英文没看懂,就看懂 ...