Websocket实现WSS

注意点:

  1. 如果网站使用HTTPS,WebSocket必须要使用wss协议
  2. 使用wss协议的连接请求必须只能写域名,而非IP+端口
  3. 通过nginx转发实现wss,内部通信就不需要使用wss了

Nginx 配置

  1. 只需要在HTTPS配置的server内加一个location即可
  2. Nginx反向代理,无论是HTTP/S或是WebSocket都会走443端口,由Nginx分发给各个项目服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ini复制代码# 代理方式实现
location = /websocket {
proxy_pass http://xxxx.cn:7303;

proxy_redirect off;
proxy_set_header Host www.xxx.cn:7303;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

# 反向代理用户信息
#proxy_set_header X-real-ip $remote_addr;
#proxy_set_header X-Forwarded-For $remote_addr;
}

Laravel

Server

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
php复制代码<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class WebSocket extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'Web {action=start}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'WebSocket description';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$arg = $this->argument('action');
switch ($arg) {
case 'start':
$this->info('WebSocket observer started');
$this->start();
break;
}
}

public function start()
{
// ssl方式
//$server = new \swoole_websocket_server("0.0.0.0", 7303, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$server = new \swoole_websocket_server("0.0.0.0", 7303);

$server->set([
//后台作为守护进程运行 'daemonize' => 1
'daemonize' => 1,
//配置SSL证书和密钥路径
//'ssl_cert_file' => "/data/php/cert/www.xxxxx.cn.pem",
//'ssl_key_file' => "/data/php/cert/www.xxxxx.cn.key"
]);

$server->on('Open', array($this, 'OnOpen'));
$server->on('Message', array($this, 'OnMessage'));
$server->on('Close', array($this, 'OnClose'));
$server->start();
}

public function OnOpen($server, $req)
{
echo "server: handshake success with fd {$req->fd}\n";
}

public function OnMessage($server, $frame)
{
var_dump($frame);
$this->send($server, $frame);
}

public function OnClose($server, $fd)
{
echo "client {$fd} closed \n";
}

public function send($server, $frame)
{
$info = json_decode($frame->data, true);
// var_dump(php_sapi_name());
switch ($info['action']) {
case 'home':
case 'device':
case 'goodsError':
case 'shopping':
$conn_list = $server->connection_list(0, 100);
if ($conn_list === false or count($conn_list) === 0) {
echo "finish \n";
}
foreach ($conn_list as $fd) {
if ($fd != $frame->fd) {
$arr = array("action" => $info['action'], "data" => $info['data']);
$data = json_encode($arr);
$server->push($fd, $data);
}
}
break;
}
}
}

Client

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
php复制代码<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class WebClient extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'SendSocket {data}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'WebClient description';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$data = $this->argument('data');

$cli = new \swoole_http_client('127.0.0.1', 7303);

$cli->setHeaders(['Trace-Id' => md5(time()),]);

$cli->on('message', function ($_cli, $frame) {
var_dump($frame);
});

$cli->upgrade('/', function ($cli) use ($cli, $data) {
$cli->push($data);
$cli->close();
});
}
}

WEB

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
scss复制代码# 地址后面必须加 /websocket
let ws = new WebSocket("wss://www.xxx.com:7300/websocket');

ws.onopen = function(evt) {
console.log("Connection open ...");
// ws.send("Hello WebSockets!");
};


// 在指定页面接取到消息指定刷新操作
ws.onmessage = function (evt) {
let hashValue = window.location.hash.split('/');
let hashLength = hashValue . length;
let newKey = hashValue[hashLength - 1];
console . log("Received Message: " + evt . data);
// ws.close();
let data = JSON . parse(evt . data);
if (data.action === 'home' && newKey === '') {
console . log('home-socket');
//home页监控
$this.homeSocket();
} else if (data.action === 'home' && newKey === 'shoppingMonitor') {
console.log('shopping-home-socket')
//购物车监控
$this.shoppingMonitorSocket();
} else if (data . action === 'shopping' && newKey === 'shoppingMonitor') {
console.log('shopping-socket');
//购物车监控
$this . shoppingMonitorSocket();
} else if (data . action === 'goodsError') {
console.log('goodsError-socket');
}
}

ws.onclose = function(e){
  //当客户端收到服务端发送的关闭连接请求时,触发onclose事件
  console.log("close");
}

ws.onerror = function(e){
  //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
  console.log(error);
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%