利用websockify将websocket通信转换成tcp

文章目录

  • 前言
  • websockify
    • websockify 介绍
    • websockify 使用
  • 探索的过程
    • 提供基础TCP服务
      • 测试可用
    • 实现Websocket客户端
    • 开始测试websockify功能
      • 再次启动websockify
      • 单独实现一个js版本websocket客户端
  • 什么是VNC
  • 总结

前言

目前遇到一个问题,原本的服务都是利用tcp通信的,但是某些平台只支持websocket,是不是要从头实现一套websocket网络收发逻辑呢?短时间内有没有替代方案呢?在经过一番寻找之后发现了websockify这个神器,可以将websocket协议转换成tcp协议,从而实现不修改应用服务就支持tcp协议的目的,接下来就说说它怎么用,以及探索的过程。

websockify

websockify 介绍

websockify 是一个用于将 WebSocket 流量转发到其他协议的工具,它的主要用途之一是将 WebSockets 转发到基于 TCP 的协议,例如 VNC(Virtual Network Computing),以下是它的一些关键特点和用途:

  • WebSocket 转发: websockify 允许你将 WebSocket 流量转发到其他类型的网络服务,使得你可以通过 WebSocket 连接访问这些服务。

  • VNC 转发: websockify 最常用于将 WebSocket 转发到 VNC 服务器。这使得你可以通过 Web 浏览器访问运行 VNC 服务的远程计算机的桌面。

  • 安全性: websockify 支持加密通信,因此可以在安全连接上运行,提供更好的数据保护。

  • 协议适配: websockify 提供了一个通用的桥接机制,允许你将 WebSocket 连接转发到支持其他协议的服务,而不仅仅是 VNC。

  • JavaScript 客户端: websockify 还包括一个 JavaScript 客户端库,可以直接在浏览器中使用,无需额外的插件。

使用 websockify 的典型场景包括在 Web 浏览器中访问远程计算机的桌面,或者通过 WebSocket 连接到其他需要 TCP 连接的服务,在实际应用中,你可以通过命令行使用 websockify,也可以将其嵌入到其他应用程序中。

websockify 使用

在Ubuntu系统下可以直接使用以下安装:

$ sudo apt install websockify

下面是一个使用示例,作用是将原本连接到8765的websocket请求转换成tcp请求,TCP端口4321

$ websockify 8765 127.0.0.1:12346

启动后原本仅支持TCP协议的服务就可以通过websockify实现对websocket的支持了

探索的过程

虽然是短短的一条 websockify 8765 127.0.0.1:12346 命令就可以实现从websocket到tcp的转换,但是探索的过程却不顺利,在发现websockify这个神器之后,首先是测试它是否能满足我们的需求,是否好用,但是直接在原有的服务上测试太费时间,所以尝试写了几个模拟的脚本。

提供基础TCP服务

最基本的我们需要一个很能提供TCP服务的程序,这里我使用python写了一个回显的服务器 echoserver.py,绑定本地的12346端口

import socketdef main():# 创建一个TCP套接字server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址和端口server_socket.bind(('127.0.0.1', 12346))# 监听连接server_socket.listen(5)print("服务器已启动,等待客户端连接...")while True:# 接受客户端连接client_socket, client_address = server_socket.accept()print(f"客户端{client_address}已连接")# 接收客户端发送的数据data = client_socket.recv(1024)print(f"收到来自{client_address}的数据: {data.decode('utf-8')}")# 将接收到的数据发送回客户端client_socket.send(data)print(f"已将数据发送回{client_address}")# 关闭客户端套接字client_socket.close()print(f"客户端{client_address}已断开连接")if __name__ == "__main__":main()

测试可用

  • 启动服务
$ python3 echoserver.py
服务器已启动,等待客户端连接...
  • 用nc命令发送tcp数据
$ echo "Hello server" | nc 127.0.0.1 12346
Hello server
  • TCP服务器看到的内容
服务器已启动,等待客户端连接...
客户端('127.0.0.1', 59214)已连接
收到来自('127.0.0.1', 59214)的数据: Hello server已将数据发送回('127.0.0.1', 59214)
客户端('127.0.0.1', 59214)已断开连接

TCP服务一切正常

实现Websocket客户端

因为python的运行环境是现成的,所以我又用它写了一个websocket客户端 wsclient.py 来发送数据,想运行的话得安装几个包

python3 -m pip install websocket
python3 -m pip install websocket-client

真实的情况下我是用websocket客户端连接nginx,然后将nginx转发到websockify监听端口,然后websockify将数据转成tcp连接应用服务,但是这个过程太复杂了,不利于说明问题,所以后面的内容我省掉nginx,假装它不存在,直接用websocket客户端连接websockify监听端口

# -*- coding: utf-8 -*-
# 运行websocket服务器import websocketdef on_message(ws, message):print(f"Received message: {message}")def on_error(ws, error):print(f"Error: {error}")def on_close(ws, close_status_code, close_msg):print(f"Connection closed with status code {close_status_code}")def on_open(ws):print("Connection opened")# 在连接建立后发送一条消息ws.send("abcd")if __name__ == "__main__":# WebSocket 服务器地址ws_url = "ws://10.10.49.172:8765"# 创建 WebSocket 连接ws = websocket.WebSocketApp(ws_url,on_message=on_message,on_error=on_error,on_close=on_close)# 设置连接建立时的回调函数ws.on_open = on_open# 启动 WebSocket 连接ws.run_forever()

为了websocket客户端的测试,我写了一个websocket服务器 wsserver.py 来接收数据,不过这不是一开始就测试了,而是在后面发现转换TCP失败查找原因,按流程分段测试时补充的脚本内容

import asyncio
import websocketsasync def echo(websocket, path):try:async for message in websocket:print(f"Received message: {message}")await websocket.send(message)except websockets.exceptions.ConnectionClosed:print("WebSocket connection closed")async def main():server = await websockets.serve(echo, "0.0.0.0", 12346)print("WebSocket server is running...")await server.wait_closed()if __name__ == "__main__":asyncio.run(main())

测试结果websocket客户端发送的数据,websocket服务器可以正常收到。

开始测试websockify功能

  • 启动tcp服务echoserver,监听12346端口
$ python3 echoserver.py
服务器已启动,等待客户端连接...
  • 启动tcp服务websockify,监听8765端口,转换到12346端口
$ websockify 8765 127.0.0.1:12346
WebSocket server settings:- Listen on :8765- No SSL/TLS support (no cert file)- proxying from :8765 to 127.0.0.1:12346
  • 运行websocket客户端发送的数据
$ python3 ./wsclient.py
Connection opened
Connection closed with status code 1003

报错了!!!

再看echoserver输出,虽然连接成功,但是收到的数据为空

客户端(‘127.0.0.1’, 55032)已连接
收到来自(‘127.0.0.1’, 55032)的数据:
已将数据发送回(‘127.0.0.1’, 55032)
客户端(‘127.0.0.1’, 55032)已断开连接

然后看下websockify输出,显示转发连接12346端口成功了,但是没有后续输出

$ websockify 8765 127.0.0.1:12346
WebSocket server settings:

  • Listen on :8765
  • No SSL/TLS support (no cert file)
  • proxying from :8765 to 127.0.0.1:12346
    10.2.48.36 - - [13/Dec/2023 20:03:11] 10.2.48.36: Plain non-SSL (ws://) WebSocket connection
    10.2.48.36 - - [13/Dec/2023 20:03:11] connecting to: 127.0.0.1:12346

定位问题吧,期间不断调整nginx配置,查看nginx和websockify日志,调整wsclient写法,调整echoserver写法,分步测试wsclient和echoserver功能都没发现问题,具体测试细节暂且不表,后来我发现可以修改websockify启动参数输出更详细的日志,测试过程如下

再次启动websockify

启动websockify再次使用wsclient测试,输出了额外的信息

$ websockify 8765 127.0.0.1:12346 --log-file /tmp/ws.log -v --traffic
WebSocket server settings:- Listen on :8765- No SSL/TLS support (no cert file)- proxying from :8765 to 127.0.0.1:12346
10.2.48.36: new handler Process
10.2.48.36 - - [13/Dec/2023 20:13:42] "GET / HTTP/1.1" 101 -
10.2.48.36 - - [13/Dec/2023 20:13:42] 10.2.48.36: Plain non-SSL (ws://) WebSocket connection
10.2.48.36 - - [13/Dec/2023 20:13:42] connecting to: 127.0.0.1:12346Traffic Legend:}  - Client receive}. - Client receive partial{  - Target receive>  - Target send>. - Target send partial<  - Client send<. - Client send partial
}.10.2.48.36 - - [13/Dec/2023 20:13:42] 127.0.0.1:12346: Client closed connection
10.2.48.36 - - [13/Dec/2023 20:13:42] 127.0.0.1:12346: Closed target

顺着结尾的两条日志 Client closed connection,我找到了这一篇问题
websockify - Client disconnects immediately after connection #365 结论说是websockify不支持发送文本了

Hmm… Are you trying to send text over that socket? We dropped support for text frames in the big cleanup.

Could you print the code and reason from the close in your close handler?

我一看我的wsclient.py可不就是发送的文本嘛,看来有救了,赶紧改成了发送bytes ws.send(b'\x01\x02\x03\x04'),但错误依旧,尝试各种发送函数无果,我严重怀疑我的换个python的websockets包有问题,所以我用html写了一个wsclient.html:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebSocket Binary Data Example</title>
</head>
<body><script>// 替换为你的 WebSocket 服务器地址const socket = new WebSocket("ws://10.10.49.172:8765");// 监听连接打开事件socket.addEventListener("open", (event) => {console.log("WebSocket connection opened.");// 构造二进制数据,这里使用一个简单的示例const binaryData = new Uint8Array([49, 50, 51, 52]);// 发送二进制数据socket.send(binaryData);console.log("Binary data sent successfully.");});// 监听接收消息事件socket.addEventListener("message", (event) => {console.log("Received message:", event.data);});// 监听连接关闭事件socket.addEventListener("close", (event) => {console.log("WebSocket connection closed.");});// 监听错误事件socket.addEventListener("error", (event) => {console.error("WebSocket error:", event);});</script>
</body>
</html>

这次终于正常了,websockify输出变成了由应用服务主动断开

$ websockify 8765 127.0.0.1:12346 --log-file /tmp/ws.log -v --traffic
WebSocket server settings:- Listen on :8765- No SSL/TLS support (no cert file)- proxying from :8765 to 127.0.0.1:12346
10.2.48.36: new handler Process
10.2.48.36 - - [13/Dec/2023 20:24:29] "GET / HTTP/1.1" 101 -
10.2.48.36 - - [13/Dec/2023 20:24:29] 10.2.48.36: Plain non-SSL (ws://) WebSocket connection
10.2.48.36 - - [13/Dec/2023 20:24:29] connecting to: 127.0.0.1:12346Traffic Legend:}  - Client receive}. - Client receive partial{  - Target receive>  - Target send>. - Target send partial<  - Client send<. - Client send partial
}>{<10.2.48.36 - - [13/Dec/2023 20:24:29] 127.0.0.1:12346: Target closed connection
10.2.48.36 - - [13/Dec/2023 20:24:29] 127.0.0.1:12346: Closed target

echoserver也看到了发送的内容【1234】:

$ python3 echoserver.py
服务器已启动,等待客户端连接...
客户端('127.0.0.1', 37438)已连接
收到来自('127.0.0.1', 37438)的数据: 1234
已将数据发送回('127.0.0.1', 37438)
客户端('127.0.0.1', 37438)已断开连接

单独实现一个js版本websocket客户端

刚刚用html里的js发送了websocket数据,需要浏览器的帮助,如果是在服务器上局限性很大,所以我调整了一下,改成了js版本websocket客户端,用node.js运行,wsclient.js内容如下:

const WebSocket = require('ws');// 替换为你的 WebSocket 服务器地址
const socket = new WebSocket("ws://10.10.49.172:8765");// 监听连接打开事件
socket.addEventListener("open", (event) => {console.log("WebSocket connection opened.");// 构造二进制数据,这里使用一个简单的示例const binaryData = new Uint8Array([49, 50, 51, 52]);// 发送二进制数据socket.send(binaryData);console.log("Binary data sent successfully.");
});// 监听接收消息事件
socket.addEventListener("message", (event) => {console.log("Received message:", event.data);
});// 监听连接关闭事件
socket.addEventListener("close", (event) => {console.log("WebSocket connection closed.");
});// 监听错误事件
socket.addEventListener("error", (event) => {console.error("WebSocket error:", event);
});

运行结果如下:

$ node wsclient.js
WebSocket connection opened.
Binary data sent successfully.
Received message: <Buffer 31 32 33 34>
WebSocket connection closed.

至此,websockify的测试就结束了,它可以满足我们的需求,将websocket请求转换成tcp请求

什么是VNC

前面在介绍websockify多次提到VNC,其实VNC (Virtual Network Computing) 是一种远程桌面协议,允许用户在一个计算机上通过网络远程控制另一个计算机的桌面。VNC 提供了一种在远程计算机上查看和操作桌面的方式,就像你坐在那台计算机前一样,以下是关于 VNC 的一些关键概念:

  • Server:在 VNC 中,远程计算机上运行的应用程序称为 VNC 服务器。该服务器负责监听连接请求,并将计算机的桌面图像发送给连接的客户端。

  • Viewer:连接到 VNC 服务器的应用程序称为 VNC 查看器。这是用户使用的远程桌面客户端,允许他们查看和操作远程计算机的桌面。

  • Port:VNC 服务器通过一个特定的网络端口监听连接请求。通常,VNC 默认使用 5900 端口。如果有多个 VNC 服务器在同一台计算机上运行,它们可能使用不同的端口(5901、5902 等)。

  • Security:VNC 提供了一些安全性选项,如密码保护和加密。这有助于确保在远程访问时保护计算机的安全。

  • Authentication:VNC 服务器和查看器之间的连接通常需要身份验证。这可以是使用密码进行简单的身份验证,也可以是更复杂的加密和密钥交换过程。

  • websockify:对于一些场景,特别是在 Web 浏览器中访问 VNC,你可能会使用工具如 websockify 将 VNC 的协议转换为 WebSocket 协议,以便在浏览器中实现 VNC 远程桌面访问。

总结

  • websockify可以轻松实现从websocket请求向tcp请求的转换,使用很方便
  • 转换路径 wsclient --ws--> websockify --tcp--> tcp application --tcp--> websockify --ws--> wsclient
  • wss对应的是ws的加密版本,他们的关系是wss=ws+SSL/TSL,类似的https=http+SSL/TSL
  • 无论是nginx还是websockify都可以配置服务器证书,将应用服务器从SSL/TSL中解脱出来
  • VNC是一种远程桌面协议,允许用户在一个计算机上通过网络远程控制另一个计算机的桌面

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

迈出这一步确实不太容易,一旦行动了就会发现没有想象中的那么难,我们都没有预知未来的能力,无法判定目前的选择是对还是错,既然选择了就要努力走下去

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/219460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

​glob --- Unix 风格路径名模式扩展​

源代码: Lib/glob.py glob 模块会按照 Unix shell 所使用的规则找出所有匹配特定模式的路径名称&#xff0c;但返回结果的顺序是不确定的。 波浪号扩展不会生效&#xff0c;但 *, ? 以及用 [] 表示的字符范围将被正确地匹配。 这是通过配合使用 os.scandir() 和 fnmatch.fnmat…

“ABCD“[(int)qrand() % 4]作用

ABCD[(int)qrand() % 4] 作用 具体来说&#xff1a; qrand() 是一个函数&#xff0c;通常在C中用于生成一个随机整数。% 4 会取 qrand() 生成的随机数除以4的余数。因为4只有四个不同的余数&#xff08;0, 1, 2, 3&#xff09;&#xff0c;所以这实际上会生成一个0到3之间的随…

java方法引用语法规则以及简单案例

目录 一、方法引用1.1 什么是方法引用1.2 方法引用的语法规则1.3 构造器引用1.4 方法引用的简单案例 参考资料 一、方法引用 1.1 什么是方法引用 方法引用是 Lambda 表达式的一种简写形式&#xff0c;用于表示已有方法的直接引用。 类似于lambda表达式&#xff0c;方法引用也…

window系统使用ESP8266开发板(CP2102)

连接开发板到电脑 虚拟机中选择连接的开发板硬件 查看设备管理器 更新驱动: CP210x USB to UART Bridge VCP Drivers - Silicon Labs 驱动安装成功

day03、关系模型之基本概念

关系模型之基本概念 1.关系模型概述1.1 关系模型三要素基本结构&#xff1a;relation/Table基本操作:relation operator 2.什么是关系3.关系模型中的完整性约束 本视频来源于B站&#xff0c;战德臣老师 1.关系模型概述 1.1 关系模型三要素 基本结构&#xff1a;relation/Table…

could not find a ready tiller pod

是 kubelet 的一个bug&#xff0c;在多container pod 的情况下有可能出现&#xff08;概率很小&#xff09; github 上已经有 PR&#xff0c;但是官方尚未合入代码 重启pod可恢复。长期来看&#xff0c;需要等待官方合入代码&#xff0c;更新版本。 解决&#xff1a; kubect…

水仙花数.

//水仙花数 #include<stdio.h> int main() { int i,a,b,c; for(i100;i<999;i) { int ai%10; int b(i/10)%10; int ci/100; if(ia*a*ab*b*bc*c*c) printf("%d ",i); } return 0; } 所谓“水仙花数”是指一个3位数&#xff0c;其各位数字立方之和等于该数本身…

使用docker实现logstash同步mysql到es

准备工作&#xff1a; 1.有mysql的连接方式&#xff0c;并且可以连接成功 2.有es的连接方式&#xff0c;并且可以连接成功 3.安装了docker 环境是Ubuntu中安装了docker 一、创建配置文件&#xff0c;用于容器卷挂载 # 切换目录&#xff0c;可自定义 cd /home/test/ # 创建lo…

FlieZilla服务器配置与数据访问、传输

概述 手机apk当初服务器&#xff0c;PC端访问手机端的数据&#xff0c;再没有数据线的情况下&#xff0c;非常方便。希望各位同仁搞起来&#xff0c;在此做个笔录。 安装包下载链接&#xff1a;https://download.csdn.net/download/qq_36075612/88577274 一、下载安装包&…

2023.12.12 关于 Java 反射详解

目录 基本概念 定义 用途 反射相关的类 反射基本原理 Class 类中的相关方法 常用获得类相关的方法 常用获得类中属性相关的方法 常用获得类中构造器相关的方法 常用获得类中方法相关的方法 实例理解 反射优缺点 基本概念 定义 Java 的反射&#xff08;reflection&a…

C++学习-2023/12/13-C++类型转换

C类型转换 static_cast 类似C语言强制类型转换 1.可以用做基本数据类型转换 2.把空类型的指针转换为目标指针类型 3.不能转换带有const属性指针 const_cast 提供一个常属性的接口 reinterpret_cast 说基本没用到 dynamic_cast:多态才会接触到 #include <iostream>…

MFC(Microsoft Foundation Classes)中 MessageBox

在MFC&#xff08;Microsoft Foundation Classes&#xff09;中&#xff0c;MessageBox是一个常用的对话框类&#xff0c;用于显示消息框并与用户进行交互。MessageBox类提供了多种用法和选项&#xff0c;以下是一些常见的用法和示例说明&#xff1a; 显示简单的消息框&#x…

算法笔记—链表、队列和栈

链表、队列和栈 1. 链表1.1 单链表反转1.2 双链表反转1.3 合并两个有序链表1.4 链表相加1.5 划分链表 2. 队列和栈2.1 循环队列2.2 栈实现队列2.3 队列实现栈2.4 最小栈2.2 双端队列 1. 链表 1.1 单链表反转 力扣 反转链表 // 反转单链表public ListNode reverseList(ListNod…

【RTOS学习】模拟实现任务切换 | 寄存器和栈的变化

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;认识任务切换&#x1f3d0;切换的实质&#x1f3d0;栈中的内容&#x1f3d0;切…

PHP中如何连接数据库并执行查询?

在 PHP 中&#xff0c;连接数据库并执行查询通常需要使用数据库扩展库。在大多数情况下&#xff0c;你可以使用以下两个扩展库&#xff1a; MySQLi&#xff08;MySQL Improved&#xff09;&#xff1a; MySQLi 是 MySQL 官方推荐的扩展库&#xff0c;提供了面向对象和面向过程两…

面试经典150题(15-19)

leetcode 150道题 计划花两个月时候刷完&#xff0c;今天&#xff08;第七天&#xff09;完成了5道(15-19)150&#xff1a; 今天这些都是我之前做过的&#xff0c;还有就是今天的全都是模拟过程。。所以做的还算快。 15&#xff08;13. 罗马数字转整数&#xff09; 题目描述&a…

基于ssm的前后端分离鲜花销售系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本鲜花销售系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

java中的包

1.包的本质分析(原理) 包的本质 实际上就是创建不同的文件夹来保存类文件 2.一个文件中有两个类的i情况 package com.use;import com.xiaoqiang.Dog;public class Test {public static void main(String[] args) {Dog dog new Dog();System.out.println(dog); //com.xiaoqian…

PHP中什么是闭包(Closure)?

在PHP中&#xff0c;闭包&#xff08;Closure&#xff09;是一种匿名函数&#xff0c;它可以作为变量传递、作为参数传递给其他函数&#xff0c;或者被作为函数的返回值。闭包可以在定义时捕获上下文中的变量&#xff0c;并在以后的执行中使用这些变量。闭包在处理回调函数、事…

vos3000外呼系统的安装需求

VOS3000 是一款成熟的 VoIP 服务器软件&#xff0c;用于呼叫中心、运营商、企业等业务场景。它具有完善的电话交换、网络电话、接口对接和账户管理等功能&#xff0c;能够提供高效可靠的 VoIP 通信服务。有关技术问题欢迎和博主一起交流。 在安装和使用 VOS3000 之前&#xff…