go-websocket服务端/客户端
websocket
websocket.Upgrader升级为websocket协议
服务端
package main
import (
"fmt"
"net/http"
"unsafe"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
//设置websocket
//CheckOrigin防止跨站点的请求伪造
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
//websocket实现
func ping(c *gin.Context) {
//升级get请求为webSocket协议
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close() //返回前关闭
for {
//读取客户端发送来到消息
mt, message, err := ws.ReadMessage()
if err != nil {
break
}
fmt.Println("服务端收到消息:",string(message))
fmt.Println("mt类型:",mt)
//写入ws数据
T:=string(message) +"收到"
msg:=*(*[]byte)(unsafe.Pointer(&T))
//服务端发送消息到客户端websocket
err = ws.WriteMessage(mt, msg)
if err != nil {
break
}
fmt.Println("发送消息:",T)
}
}
func main() {
r := gin.Default()
r.GET("/ping", ping)
r.Run(":8080")
}
客户端
package main
import (
"fmt"
"log"
"net/url"
"strconv"
"sync"
"time"
"github.com/gorilla/websocket"
)
type websocketClientManager struct {
conn *websocket.Conn
addr *string
path string
sendMsgChan chan string
recvMsgChan chan string
isAlive bool
timeout int
}
// 构造函数
func NewWsClientManager(addrIp, addrPort, path string, timeout int) *websocketClientManager {
addrString := addrIp + ":" + addrPort
var sendChan = make(chan string, 10) //定义channel大小,需要及时处理消费,否则会阻塞
var recvChan = make(chan string, 10) //定义channel大小,需要及时处理消费,否则会阻塞
var conn *websocket.Conn
return &websocketClientManager{
addr: &addrString,
path: path,
conn: conn,
sendMsgChan: sendChan,
recvMsgChan: recvChan,
isAlive: false,
timeout: timeout,
}
}
// 链接服务端
func (wsc *websocketClientManager) dail() {
var err error
u := url.URL{Scheme: "ws", Host: *wsc.addr, Path: wsc.path}
fmt.Println("connecting to:", u.String())
wsc.conn, _, err = websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
fmt.Println(err)
return
}
wsc.isAlive = true
log.Printf("connecting to %s 链接成功!!!", u.String())
}
// 发送消息到服务端
func (wsc *websocketClientManager) sendMsgThread() {
go func() {
for {
msg := <-wsc.sendMsgChan
fmt.Println("发送消息:",msg)
// websocket.TextMessage类型
err := wsc.conn.WriteMessage(websocket.TextMessage, []byte(msg))
if err != nil {
fmt.Println("write:", err)
continue
}
}
}()
}
// 读取服务端消息
func (wsc *websocketClientManager) readMsgThread() {
go func() {
for {
if wsc.conn != nil {
_, message, err := wsc.conn.ReadMessage()
if err != nil {
log.Println("readErr:", err)
wsc.isAlive = false
// 出现错误,退出读取,尝试重连
break
}
// 需要读取数据,不然会阻塞
wsc.recvMsgChan <- string(message)
}
}
}()
}
// 开启服务并重连
func (wsc *websocketClientManager) start() {
for {
if wsc.isAlive == false {
wsc.dail()
wsc.sendMsgThread()
wsc.readMsgThread()
wsc.Msg() //构造假消息
wsc.Recv() //接收处理服务端返回到消息
}
time.Sleep(time.Second * time.Duration(wsc.timeout))
}
}
//模拟websocket心跳包,假数据
func (wsc *websocketClientManager)Msg() {
go func() {
a:=0
for {
wsc.sendMsgChan <- strconv.Itoa(a)
time.Sleep(time.Second*1)
a+=1
}
}()
}
//接收处理服务端返回到消息
func (wsc *websocketClientManager) Recv() {
go func() {
for {
msg, ok := <-wsc.recvMsgChan
if ok {
fmt.Println("收到消息:",msg)
}
}
}()
}
func main() {
wsc := NewWsClientManager("127.0.0.1", "8080", "/ping", 10)
wsc.start()
var w1 sync.WaitGroup
w1.Add(1)
w1.Wait()
}
go-websocket服务端/客户端的更多相关文章
- C# WebSocket 服务端示例代码 + HTML5客户端示例代码
WebSocket服务端 C#示例代码 using System; using System.Collections.Generic; using System.Linq; using System. ...
- socket-WebSocket HttpListener TcpListener 服务端客户端的具体使用案例
/// <summary>/// 启动服务监听的ip和端口的主线程/// </summary>/// <param name="tunnelPort" ...
- socket-WebSocket-HttpListener-TcpListener服务端客户端的具体使用案例
/// <summary> /// 启动服务监听的ip和端口的主线程 /// </summary> /// <param name="tunnelPort&qu ...
- nodejs搭建简单的websocket服务端
创建websocket服务端使用了nodejs-websocket ,首先要安装nodejs-websocket,在项目的目录下: npm install nodejs-websocket 1.搭建w ...
- WebSocket服务端
http://blog.csdn.net/qq_20282263/article/details/54310737 C# 实现WebSocket服务端 原创 2017年01月10日 09:22:50 ...
- asp.net网站作为websocket服务端的应用该如何写
最近被websocket的一个问题困扰了很久,有一个需求是在web网站中搭建websocket服务.客户端通过网页与服务器建立连接,然后服务器根据ip给客户端网页发送信息. 其实,这个需求并不难,只是 ...
- Netty 搭建 WebSocket 服务端
一.编码器.解码器 ... ... @Autowired private HttpRequestHandler httpRequestHandler; @Autowired private TextW ...
- react服务端/客户端,同构代码心得
FKP-REST是一套全栈javascript框架 react服务端/客户端,同构代码心得 作者:webkixi react服务端/客户端,同构代码心得 服务端,客户端同构一套代码,大前端的梦想, ...
- 基于JAX-WS的Web Service服务端/客户端 ;JAX-WS + Spring 开发webservice
一.基于JAX-WS的Web Service服务端/客户端 下面描述的是在main函数中使用JAX-WS的Web Service的方法,不是在web工程里访问,在web工程里访问,参加第二节. JAX ...
随机推荐
- httpRunner使用小结
1.每个系统可以给所有相关接口准备一份完整的主流程数据,这样就不用每执行一条用例就要先执行很多前置用例2.每条用例在设计之初,关于使用的前置数据,以及条件判断的数据值,以及设置的前提条件数据值,尽量保 ...
- JavaScript使用原型链实现继承
JavaScript实现继承的思想: 一句话总结,让子类的原型等于父类的实例. 详细来说,其实利用了原型的性质即在JavaScript中所有被实例化对象具有相同的原型属性和方法,每一个被实例化对象的原 ...
- List、Set、Map详解及区别
一.List接口 List是一个继承于Collection的接口,即List是集合中的一种.List是有序的队列,List中的每一个元素都有一个索引:第一个元素的索引值是0,往后的元素的索引值依次+1 ...
- Spring 配置文件 ?
Spring 配置文件是个 XML 文件,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用.
- 学习MFS(三)
1.MooseFS是什么 一个类MooseFS是一个具备冗余容错功能的分布式网络文件系统,它将数据分别存放在多个物理服务器或单独磁盘或分区上,确保一份数据有多个备份副本,然而对于访问MFS的客户端或者 ...
- Python - 数据存储与数据库简介
- Java基础学习之“二维数组”
一.鄙人对二维数组的理解 二维数组就是由多个数组并列而成 二.举例 1.普通数组(一维数组)的图像格式 2.二维数组的图像格式 代码 1 @Test 2 public void xueXi(){ 3 ...
- 你可以说出export export default || model.exports exports 的区别吗(一)
一.前言: 用模块写代码,为什么要用模块来写代码:ES6之前,在js中定义的一切,都是共享一个全局作用域的,随着web应用变得复杂,这样做会引起如:命名冲突和安全问题.于是引入了模块. 二.清楚一个概 ...
- hibernate数据源
Hibernate的描述文件可以是一个properties属性文件,也可以是一个xml文件.下面讲一下Hibernate.cfg.xml的配置.配置格式如下:1. 配置数据源 在Hibernate ...
- java反射相关
反射的机制:反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言 ...