编程 Golang实现的交互Shell

2024-11-19 04:05:20 +0800 CST views 1199

Golang实现的交互Shell

最近在用Golang编写交互Shell的代码,涉及三端(浏览器、服务端、agent)需要一个WebSocket转发来实现它们之间的通讯。

问题与基本架构

  1. 如何实现WebSocket转发,打通浏览器和agent的通讯?

    基本架构如下:

    浏览器 -> 服务端 -> agent
    agent -> 服务端 -> 浏览器
    
  2. 如何将浏览器和agent对应起来?

    我打算在服务端实现以下逻辑:

    • 浏览器通过唯一标识连接到服务端的 handler1,将连接和唯一标识存储在全局中(handler1 只接收浏览器的连接)。
    • agent 通过唯一标识连接到服务端的 handler2,通过唯一标识打通浏览器和agent。

    这里不贴出浏览器和agent的具体代码。

使用到的项目

划重点

要想打通浏览器和agent的通讯,服务端作为中间人,需要进行以下操作。以下是服务端代码示例,非常优雅:

serverClosed := make(chan struct{})
clientClosed := make(chan struct{})
go copyConn(client.ws, ws, serverClosed, clientClosed)
go copyConn(ws, client.ws, clientClosed, serverClosed)

copyConn 函数

func copyConn(readConn, writeConn *websocket.Conn, readClosed, writeClosed chan struct{}) {
    var rerr error
    for {
        var r io.Reader
        var messageType int

        messageType, r, rerr = readConn.NextReader()
        if rerr != nil {
            break
        }
        w, err := writeConn.NextWriter(messageType)
        if err != nil {
            break
        }
        if _, err := io.Copy(w, r); err != nil {
            break
        }
        if err := w.Close(); err != nil {
            break
        }
    }

    readConn.Close()
    close(readClosed)

    if e, ok := rerr.(*websocket.CloseError); ok && e.Code != websocket.CloseAbnormalClosure {
        var m []byte
        if e.Code != websocket.CloseNoStatusReceived {
            m = websocket.FormatCloseMessage(e.Code, e.Text)
        }
        err := writeConn.WriteMessage(websocket.CloseMessage, m)

        if err == nil {
            select {
            case <-writeClosed:
                return
            case <-time.After(10 * time.Second):
            }
        }
    }
    writeConn.Close()
}

注意事项

仅限交流学习使用,如您在使用本工具或代码的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。如侵权请私聊删文。

复制全文 生成海报 编程 网络通讯 Golang WebSocket 软件开发

推荐文章

CSS Grid 和 Flexbox 的主要区别
2024-11-18 23:09:50 +0800 CST
Vue3中如何进行异步组件的加载?
2024-11-17 04:29:53 +0800 CST
在 Rust 中使用 OpenCV 进行绘图
2024-11-19 06:58:07 +0800 CST
H5抖音商城小黄车购物系统
2024-11-19 08:04:29 +0800 CST
go发送邮件代码
2024-11-18 18:30:31 +0800 CST
windows下mysql使用source导入数据
2024-11-17 05:03:50 +0800 CST
PHP 压缩包脚本功能说明
2024-11-19 03:35:29 +0800 CST
Python 基于 SSE 实现流式模式
2025-02-16 17:21:01 +0800 CST
初学者的 Rust Web 开发指南
2024-11-18 10:51:35 +0800 CST
设置mysql支持emoji表情
2024-11-17 04:59:45 +0800 CST
Vue 3 中的 Fragments 是什么?
2024-11-17 17:05:46 +0800 CST
小技巧vscode去除空格方法
2024-11-17 05:00:30 +0800 CST
Mysql允许外网访问详细流程
2024-11-17 05:03:26 +0800 CST
浏览器自动播放策略
2024-11-19 08:54:41 +0800 CST
PHP 允许跨域的终极解决办法
2024-11-19 08:12:52 +0800 CST
Nginx 反向代理
2024-11-19 08:02:10 +0800 CST
关于 `nohup` 和 `&` 的使用说明
2024-11-19 08:49:44 +0800 CST
Vue3中怎样处理组件引用?
2024-11-18 23:17:15 +0800 CST
使用 Git 制作升级包
2024-11-19 02:19:48 +0800 CST
Grid布局的简洁性和高效性
2024-11-18 03:48:02 +0800 CST
跟着 IP 地址,我能找到你家不?
2024-11-18 12:12:54 +0800 CST
程序员茄子在线接单