-
老雷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
|
<?php class 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.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式