方式一 :通过 swoole 的request 对象获取客户端IP
场景: 客户端直接远程使用IP+端口访问webscoket服务。
关键核心代码如下:
$server->on('message', function($server, $frame) {
$res = $server->getClientInfo($frame->fd);
$ip = $res[‘remote_ip’];
}$res 具体数据格式:
array(11) {
["websocket_status"]=>int(3)
["server_port"]=>int(9502)
["server_fd"]=>int(9)
["socket_fd"]=>int(23)
["socket_type"]=>int(1)
["remote_port"]=>int(50758)
["remote_ip"]=>string(9) "127.0.0.1"
["reactor_id"]=>int(3)
["connect_time"]=>int(1565747287)
["last_time"]=>int(1565747287)
["close_errno"]=>int(0)
}提示: 远程开放socket端口不安全,不建议此方式
方式二: 通过 nginx 反向代理到 webscoket 获取客户端IP
首先配置nginx反向代理,配置关键代码如下:
location /websocket {
proxy_redirect off;
proxy_pass #websocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr; #配置IP
}假设我们这里配置的域名是:www.lakeui.com
场景: 客户端通过域名访问webscoket服务。
例如: ws://www.lakeui.com/webscoket
由于所有客户端都是通过nginx代理到websocket,所以websocket再通过方法一获取的ip都是127.0.0.1 ,这里的关键就在nginx的反向代理配置:
proxy_set_header X-Forwarded-For $remote_addr;
表示将客户端IP通过头信息传递给websocket,webscoket可以通过头信息获取客户端IP,关键核心代码如下:
$server->on('open', function($server, $req) {
$ip = $req->header['x-forwarded-for'];
});本以为可以结束了,可实际swoole只有在open回调方法中才能获取request对象,可业务一般在message回调中处理,ip又如何获取和传递了?
查询了swoole相关文档,没有找到相应的获取方法于是只有想办法将ip传递。关键代码如下:
$ips = []; //定义一个全局ip存放数组
$server->on('open', function($server, $req) {
global $ips;
$ips[$req->fd] = $req->header['x-forwarded-for']; //将客户端标示与IP关联存入全局数组
});
$server->on('message', function($server, $frame) {
global $ips;
$ip = $ips[$frame->fd]; //获取客户端IP
});
//注意一定要释放ip,否则会导致内存爆掉
$server->on('close', function($server, $fd) {
global $ips;
unset($ips[$fd]); //客户端断开时清除ip关联
});以上方式是目前我发现的解决办法,如果各位大神又更好的解决方法,可以留言或者联系我,一起共同学习!


