php实现socket推送技术的示例

2025-05-27 0 82

socket出现之前已经有ajax定时请求、长轮询等方案,但都不能满足需求,socket就应用而生了。

socket基本函数socket

总结下常用的socket函数

服务端: socket_create 创建socket设置基本参数

     socket_bind 绑定ip和端口号

     socket_listen 监听

     socket_accept 客户端的连接

     socket_read 读取客户端的数据

     socket_write 给单独客户端发送数据

     socket_close 关闭连接

客户端:socket_create 创建socket设置基本参数

     socket_connect 连接socket

     socket_write 给服务端发送数据

     socket_read 读取服务端数据

     socket_close 关闭连接

H5websocket不多说了,上链接

OK,开始贴代码~

———————————————————-分割线

服务端代码:

?

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

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146
<?php

class WS {

var $master;

var $sockets = array();

var $debug = false;//true为调试模式,输出log日志

var $handshake = array();

function __construct($address, $port){

$this->master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() failed");

socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("socket_option() failed");

socket_bind($this->master, $address, $port) or die("socket_bind() failed");

socket_listen($this->master,20) or die("socket_listen() failed");

$this->sockets[] = $this->master;

$this->say("Server Started : ".date('Y-m-d H:i:s'));

$this->say("Listening on : ".$address." port ".$port);

$this->say("Master socket : ".$this->master."\\n");

while(true){

$socketArr = $this->sockets;

$write = NULL;

$except = NULL;

socket_select($socketArr, $write, $except, NULL); //自动选择来消息的socket 如果是握手 自动选择主机

foreach ($socketArr as $socket){

if ($socket == $this->master){ //主机

$client = socket_accept($this->master);

if ($client < 0){

$this->log("socket_accept() failed");

continue;

} else{

$this->connect($client);

}

} else {

$bytes = @socket_recv($socket,$buffer,2048,0);

if ($bytes == 0){

$this->disConnect($socket);

}

else{

$key = array_search($socket, $this->sockets);

if (empty($this->handshake) || !isset($this->handshake[$key]) || !$this->handshake[$key]){

$this->doHandShake($socket, $buffer, $key);

}

else{

$buffer = $this->decode($buffer);

echo $buffer.PHP_EOL;

$key = array_search($socket, $this->sockets);

$arr = $this->sockets;

array_shift($arr);

foreach ($arr as $s){

$this->send($s, $buffer);

}

}

}

}

}

}

}

function send($client, $msg){

$msg = $this->frame($msg);

socket_write($client, $msg, strlen($msg));

}

function connect($socket){

array_push($this->sockets, $socket);

$this->say("\\n" . $socket . " CONNECTED!");

$this->say(date("Y-n-d H:i:s"));

}

function disConnect($socket){

$index = array_search($socket, $this->sockets);

socket_close($socket);

$this->say($socket . " DISCONNECTED!");

if ($index >= 0){

echo 'unset index is:'.PHP_EOL;

unset($this->sockets[$index]);

}

}

function doHandShake($socket, $buffer, $handKey){

$this->log("\\nRequesting handshake...");

$this->log($buffer);

list($resource, $host, $origin, $key) = $this->getHeaders($buffer);

$this->log("Handshaking...");

$upgrade = "HTTP/1.1 101 Switching Protocol\\r\\n" .

"Upgrade: websocket\\r\\n" .

"Connection: Upgrade\\r\\n" .

"Sec-WebSocket-Accept: " . $this->calcKey($key) . "\\r\\n\\r\\n"; //必须以两个回车结尾

$this->log($upgrade);

$sent = socket_write($socket, $upgrade, strlen($upgrade));

$this->handshake[$handKey]=true;

$this->log("Done handshaking...");

return true;

}

function getHeaders($req){

$r = $h = $o = $key = null;

if (preg_match("/GET (.*) HTTP/" ,$req,$match)) { $r = $match[1]; }

if (preg_match("/Host: (.*)\\r\\n/" ,$req,$match)) { $h = $match[1]; }

if (preg_match("/Origin: (.*)\\r\\n/" ,$req,$match)) { $o = $match[1]; }

if (preg_match("/Sec-WebSocket-Key: (.*)\\r\\n/",$req,$match)) { $key = $match[1]; }

return array($r, $h, $o, $key);

}

function calcKey($key){

//基于websocket version 13

$accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));

return $accept;

}

function decode($buffer) {

$len = $masks = $data = $decoded = null;

$len = ord($buffer[1]) & 127;

if ($len === 126) {

$masks = substr($buffer, 4, 4);

$data = substr($buffer, 8);

}

else if ($len === 127) {

$masks = substr($buffer, 10, 4);

$data = substr($buffer, 14);

}

else {

$masks = substr($buffer, 2, 4);

$data = substr($buffer, 6);

}

for ($index = 0; $index < strlen($data); $index++) {

$decoded .= $data[$index] ^ $masks[$index % 4];

}

return $decoded;

}

function frame($s){

$a = str_split($s, 125);

if (count($a) == 1){

return "\\x81" . chr(strlen($a[0])) . $a[0];

}

$ns = "";

foreach ($a as $o){

$ns .= "\\x81" . chr(strlen($o)) . $o;

}

return $ns;

}

function say($msg = ""){

echo $msg . "\\n";

}

function log($msg = ""){

if ($this->debug){

echo $msg . "\\n";

}

}

}

new WS('localhost', 4000);

客户端代码(H5):

?

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
<html>

<head>

<title>demo</title>

<script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>

</head>

<body>

<input type="text" id="content">

<input type="button" value="send" id="send">

<script type="text/javascript">

var ws = new WebSocket("ws://localhost:4000");

ws.onopen = function(){

console.log("握手成功");

}

ws.onmessage = function(e){

console.log("message:" + e.data);

}

ws.onerror = function(){

console.log("error");

}

$("#send").click(function(){

content = $("#content").val();

console.log(content);

ws.send(content);

})

</script>

</body>

</html>

然后执行php demo.php 开启socket(从运维那偷学一招,linux下执行nohup php demo.php &可以在后台执行),浏览器打开多个index.html,就能建立通讯了。

代码解析:

1.属性$sockets数组保存每个accept连接(不知道这么描述对不对);

2.属性$handshake数组保存连接是否在连接状态;

以上这篇php实现socket推送技术的示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持快网idc。

原文链接:http://www.cnblogs.com/kkform/archive/2017/12/20/8072836.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 php实现socket推送技术的示例 https://www.kuaiidc.com/71691.html

相关文章

发表评论
暂无评论