golang语言websocket百万长链接

news2024/10/6 8:33:35

是简单demo测试

前端

<html>
<head>
    <title>Simple client</title>

    <script type="text/javascript">
        var ws;

        function init() {
            // Connect to Web Socket
            ws = new WebSocket("ws://localhost:8866/ws");
            // Set event handlers.
            ws.onopen = function() {
                output("onopen");
            };

            ws.onmessage = function(e) {
                // e.data contains received string.
                output("onmessage: " + e.data);
            };

            ws.onclose = function() {
                output("onclose");
            };
            ws.onerror = function(e) {
                output("onerror");
                console.log(e)
            };
        }

        function onSubmit() {
            var input = document.getElementById("input");
            // You can send message to the Web Socket using ws.send.
            ws.send(input.value);
            output("send: " + input.value);
            input.value = "";
            input.focus();
        }

        function onCloseClick() {
            ws.close();
        }

        function output(str) {
            var log = document.getElementById("log");
            var escaped = str.replace(/&/, "&amp;").replace(/</, "&lt;").
            replace(/>/, "&gt;").replace(/"/, "&quot;"); // "
            log.innerHTML = escaped + "<br>" + log.innerHTML;
        }
    </script>
</head>
<body onload="init();">
<form onsubmit="onSubmit(); return false;">
    <input type="text" id="input">
    <input type="submit" value="Send">
    <button onclick="onCloseClick(); return false;">close</button>
</form>
<div id="log"></div>
</body>
</html>

后端

主服务

package main

import (
	"bytes"
	"github.com/gorilla/websocket"
	"net/http"
	"time"
	"websocket/impl"
)

func main() {
	http.HandleFunc("/ws", wsHandle)

	http.ListenAndServe("0.0.0.0:8866", nil)
}

//定义转换器
var (
	upgrader = websocket.Upgrader{
		//允许跨域
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

func wsHandle(w http.ResponseWriter, r *http.Request) {
	var (
		wsConn *websocket.Conn
		err    error
		data   []byte
		conn   *impl.Connection
	)

	if wsConn, err = upgrader.Upgrade(w, r, nil); err != nil {
		return
	}
	if conn, err = impl.InitConnetion(wsConn); err != nil {
		goto ERR
	}
	go func() {
		var (
			err error
		)
		for {
			if err = conn.WriteMessage([]byte("heartbeat")); err != nil {
				return
			}
			time.Sleep(5 * time.Second)
		}
	}()

	for {
		if data, err = conn.ReadMessage(); err != nil {
			goto ERR
		}
		if err = conn.WriteMessage(data); err != nil {
			goto ERR
		}
	}
ERR:
	//todo关闭连接操作
	conn.Close()
}

func BytesCombine1(pBytes ...[]byte) []byte {
	length := len(pBytes)
	s := make([][]byte, length)
	for index := 0; index < length; index++ {
		s[index] = pBytes[index]
	}
	sep := []byte("")
	return bytes.Join(s, sep)
}

接口封装

package impl

import (
	"errors"
	"github.com/gorilla/websocket"
	"sync"
)

type Connection struct {
	wsConn       *websocket.Conn
	inChannel    chan []byte
	outChannel   chan []byte
	closeChannel chan byte
	isClose      bool
	mutex        sync.Mutex
}

func InitConnetion(wsConn *websocket.Conn) (conn *Connection, err error) {
	conn = &Connection{
		wsConn:       wsConn,
		inChannel:    make(chan []byte, 1000),
		outChannel:   make(chan []byte, 1000),
		closeChannel: make(chan byte, 1),
	}
	//读协程
	go conn.readLoop()
	go conn.writeLoop()
	return
}
func (conn *Connection) ReadMessage() (data []byte, err error) {
	select {
	case data = <-conn.inChannel:
	case <-conn.closeChannel:
		err = errors.New("connection 已关闭")

	}
	return
}

func (conn *Connection) WriteMessage(data []byte) (err error) {

	select {
	case conn.outChannel <- data:
	case <-conn.closeChannel:
		err = errors.New("connection 已关闭")

	}
	return
}

func (conn *Connection) Close() {
	conn.wsConn.Close()
	if !conn.isClose {
		close(conn.closeChannel)
		conn.isClose = true
	}
	conn.mutex.Unlock()
}

//内部实现
func (conn *Connection) readLoop() {
	var (
		data []byte
		err  error
	)

	for {
		select {
		case conn.inChannel <- data:
		case <-conn.closeChannel:
			goto ERR

		}
		if _, data, err = conn.wsConn.ReadMessage(); err != nil {
			goto ERR
		}

		conn.inChannel <- data
	}
ERR:
	conn.Close()
}

func (conn *Connection) writeLoop() {
	var (
		data []byte
		err  error
	)
	for {
		data = <-conn.outChannel
		if conn.wsConn.WriteMessage(websocket.TextMessage, data); err != nil {
			goto ERR
		}
	}
ERR:
	conn.Close()
}

效果

在这里插入图片描述

优化

内核瓶颈

cup 最理想的处理大概是每秒100万次,已经到了极限

  1. 减少网络小包的发送,小包大概几百字节,把同一秒中的推送的条数合并成一条,合并后每秒推送的次数等于连接数

锁瓶颈

  1. 打包json

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

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

相关文章

联合证券|再创纪录,外资狂买超1000亿!券商、期货板块持续活跃

A股今天全线上扬&#xff0c;沪指小幅走高&#xff0c;创业板、科创50指数体现强势&#xff1b;港股走势疲弱&#xff0c;恒生科技指数一度跌超2%。 详细来看&#xff0c;两市股指盘中震动上扬&#xff0c;午后全线走高&#xff0c;创业板指、科创50指数涨超1%&#xff1b;到收…

PCB板缺陷检测识别系统 YOLOv7

PCB板缺陷检测识别系统通过YOLOv7网络深度学习技术&#xff0c;对现场PCB是否存在缺陷部分进行实时分析检测&#xff0c;当检测到PCB本身存在缺陷的时候&#xff0c;立即抓拍存档告警方便后期针对性的进行调整改。YOLO系列算法是一类典型的one-stage目标检测算法&#xff0c;其…

CSS+JS 折叠

文章目录CSSJS 折叠效果CSSjQuery 鼠标经过显示详细信息CSSJS 折叠效果 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>折叠效果</title><style type"text/css">.collapse-box {width: 500px;borde…

FMC子卡设计资料原理图:FMC177-基于AD9361的双收双发射频FMC子卡

FMC177-基于AD9361的双收双发射频FMC子卡一、板卡介绍 FMC177射频模块分别包含两个接收通道与发射通道&#xff0c;其频率可覆盖达到70MHz~6GHz&#xff0c;AD9361芯片提供具有成本效益的实验平台&#xff0c;具有达到56MHz的瞬时带宽&#xff0c;更高的灵敏度&#xff…

Java 23种设计模式(2.创建者模式-单例设计模式)

1. 创建者模式 创建型模式分为&#xff1a; 单例模式工厂方法模式抽象工程模式原型模式建造者模式 什么是创建者模式&#xff1f; 创建型模式的主要关注点是“怎样创建对象&#xff1f;”&#xff0c;它的主要特点是“将对象的创建与使用分离”。 这样可以降低系统的耦合度…

Windows 下 VS Code 远程连接 Ubuntu 并配置免密登录

文章目录1.安装 Visual Studio Code2.安装必要的插件3.为本机生成 SSH 密钥对4.将公钥拷贝到 Ubuntu 上5.配置 Remote 插件6.关闭远程连接7.卸载 Visual Studio Code7.1 在控制面板中找到 Visual Studio Code 将其卸载7.2 删除之前安装过的插件7.3 删除用户信息和缓存信息1.安装…

BootStrap使用笔记+案例

前端开发 第三节BootStrap BootStrap BootStrap是别人写好的CSS样式&#xff0c;如何使用BootStrap&#xff1a; 下载BootStrap使用 在页面上引入BootStrap编写HTML时&#xff0c;按照BootStrap的规定来编写 自定制 开发版本&#xff1a;bootstrap.css 生产版本&#xf…

【HTML | CSS】春节将至,为网页挂上精美的灯笼吧(附源码)程序员的浪漫

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

在线支付系列【2】支付宝和微信支付发展史

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录支付宝发展史起步阶段发展阶段上升阶段微信支付发展史支付宝 支付宝是阿里巴巴集团于 2004 年推出的一款第三方支付的产品&#xff0c;目前隶属于蚂蚁金服&#xff08;杭州&#xff09;网络技术…

2023年最推荐苹果、华为、荣耀:一场“以人为中心”的口碑竞技

消费者需求是市场发展的风向标。经济学界早有洞察&#xff0c;诺贝尔经济学奖得主哈耶克曾提出“消费者主权”理论&#xff0c;认为生产什么&#xff0c;生产多少&#xff0c;应当由消费者的意愿和偏好决定。手机市场也是如此&#xff0c;存量竞争下&#xff0c;消费者进一步掌…

软件测试复习09:集成测试、系统测试、验收测试、回归测试

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录集成测试集成测试方法自顶向下自底向上系统测试验收测试回归测试集成测试 把模块拼装到一起&#…

【电力系统经济调度】多元宇宙算法求解电力系统多目标优化问题(Matlab实现)【电气期刊论文复现】

目录 0 概述 1 环境经济调度数学模型 2 多元宇宙算法 3 运行结果 4 Matlab代码实现 目录 0 概述 1 环境经济调度数学模型 2 多元宇宙算法 3 Matlab代码实现 3.1 主函数&#xff1a; 3.2 目标函数 4 运行结果 0 概述 多元宇宙算法求解电力系统多目标优化算法有…

【GD32F427开发板试用】CAN总线了解和回环测试

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;HonestQiao CAN总线是个好东西&#xff0c;据说用了的都说好。只要是09年之后的车都有CAN总线&#xff0c;要是摸得透的话&#xff0c;你还能通…

微信小程序开发尚学堂 介绍 项目结构 组件

一、微信小程序介绍1. 微信小程序介绍微信小程序&#xff0c;简称小程序&#xff0c;是一种不需要下载安装即可使用的应用&#xff0c;它实现了应用”触手可及”的梦想&#xff0c;用户扫一扫或搜一下即可打开应用。说明&#xff1a;小程序是需要下载的&#xff0c;小程序的占用…

用于多核DSP开发的核间通信

TI的多核DSP以TMS320C6678为例&#xff0c;它是多核同构的处理器&#xff0c;内部是8个相同的C66x CorePac。对其中任意一个核的开发就和单核DSP开发的流程是类似的。   但是如果仅仅只是每个核独立开发&#xff0c;那么很难体现出多核的优势。要充分发挥多核处理器的性能&am…

Docker 应用实践-容器篇

在 Docker 镜像篇中&#xff0c;我们了解到 Docker 镜像类似于模板&#xff0c;那么 Docker 容器就相当于从模板复制过来运行时的实例&#xff0c;Docker 容器可以被创建、复制、暂停和删除等。 每一个 Docker 容器在运行时都是以镜像为基础层&#xff0c;并在镜像的基础上创建…

PWM 应用

1.PWM 同样也是通过 sysfs 方式进行操控&#xff0c;进入到/sys/class/pwm 目录下。8 个以 pwmchipX&#xff08;X 表示数字 0~7&#xff09;命名的文件夹&#xff0c;这八个文件夹其实就对应了 I.MX6U的 8 个 PWM 控制器&#xff0c; I.MX6U 总共有 8 个 PWM 控制器。2.进入到…

云GPU服务器部署及pycharm远程连接

我们在之前使用CoLab来运行项目&#xff0c;但其存在时长限制问题所以并不是很理想&#xff0c;今天博主发现腾讯云服务目前在搞活动&#xff0c;比较实惠&#xff0c;便买了一台来体验一下。 直接搜索gpu服务器租用即可找到 购买服务器 博主买的是NVIDIA T4 GPU,还是较有性…

web流程设计器andflow_js已支持自定义颜色

andflow_js 是一个web 开源流程设计框架&#xff0c;目前版本已支持对各类节点单独设置颜色。除了颜色之外&#xff0c;andflow_js还支持通过setActionInfo、setGroupInfo、setListInfo、setTipInfo 等设置节点各种参数。 设置节点的颜色&#xff1a; 设置节点边框颜色 and…

Arduino环境下对NodeMCU ESP8266的闪存flash系统使用

flash存储简答介绍 参考&#xff1a;https://www.elecfans.com/consume/572040.html flash存储器又称闪存&#xff08;快闪存储器&#xff09;&#xff0c;就其本质而言&#xff0c;flash存储器属于EEPROM&#xff08;电擦除可编程只读存储器&#xff09;类型。是一种长寿命的…