-
老雷socket编程之PHP利用socket扩展实现聊天服务
老雷socket编程之PHP利用socket扩展实现聊天服务
socket聊天服务原理

PHP有两个socket的扩展 sockets和streams
sockets
socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
socket_write
socket_read
socket_close
客户端
socket_connect($socket, $address, $service_port);
服务端
socket_bind($sock, $address, $port)
socket_listen($sock)
socket_accept
Streams
客户端
stream_socket_client
fwrite
fread
fclose($fp);
服务端
stream_socket_server
stream_set_blocking
stream_select
stream_socket_accept conn
stream_socket_recvfrom
stream_socket_sendto
stream_socket_shutdown
课后练习
使用sockets和streams扩展实现客户端跟服务端的功能。
服务端代码 客服端可使用udp&tcp测试工具
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
<?phpclass SocketService{ public $host="tcp://0.0.0.0:8000"; private $address; private $port; private $_sockets; public $clients; public $maxid=1000; public function __construct($address = '', $port='') { if(!empty($address)){ $this->address = $address; } if(!empty($port)) { $this->port = $port; } } public function onConnect($client_id){ echo "Client client_id:{$client_id} \n"; } public function onMessage($client_id,$msg){ //发给所有的 foreach($this->clients as $kk=>$cc){ if($kk>0){ $this->send($cc, $msg); } } } public function onClose($client_id){ echo "$client_id close \n"; } public function service(){ //获取tcp协议号码。 $tcp = getprotobyname("tcp"); $sock = stream_socket_server($this->host, $errno, $errstr);; if(!$sock) { throw new Exception("failed to create socket: ".socket_strerror($sock)."\n"); } stream_set_blocking($sock,0); $this->_sockets = $sock; echo "listen on $this->address $this->host ... \n"; } public function run(){ $this->service(); $this->clients[] = $this->_sockets; while (true){ $changes = $this->clients; //$write = NULL; //$except = NULL; stream_select($changes, $write, $except, NULL); foreach ($changes as $key => $_sock){ if($this->_sockets == $_sock){ //判断是不是新接入的socket if(($newClient = stream_socket_accept($_sock)) === false){ unset($this->clients[$key]); continue; } $line = trim(stream_socket_recvfrom($newClient, 1024)); $this->maxid++; $this->clients[$this->maxid] = $newClient; $this->onConnect($this->maxid); } else { $msg=@stream_socket_recvfrom($_sock, 2048); if(!$msg){ stream_socket_shutdown($this->clients[$key],STREAM_SHUT_RDWR); unset($this->clients[$key]); $this->onClose($key); }else{ $msg=$this->decode($msg); $this->onMessage($key,$msg); } } } } } /** * 发送数据 * @param $newClinet 新接入的socket * @param $msg 要发送的数据 * @return int|string */ public function send($newClinet, $msg){ $msg=$this->encode($msg); if($msg){ stream_socket_sendto($newClinet, $msg); } } public function encode($msg){ return $msg . "\n"; } public function decode($msg){ return rtrim($msg, "\r\n"); } /** * 关闭socket */ public function close(){ return socket_close($this->_sockets); }} $sock = new SocketService('127.0.0.1','9000');$sock->run(); |
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式










