www.91084.com

GVKun编程网logo

golang go语言 http包 和 高并发下的websocket(golang 高并发http请求)

16

针对golanggo语言http包和高并发下的websocket和golang高并发http请求这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展golanggorillawebsocket例

针对golang go语言 http包 和 高并发下的websocketgolang 高并发http请求这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展golang gorilla websocket例子、Golang websocket、golang websocket 入门、Golang websocket使用方法等相关知识,希望可以帮助到你。

本文目录一览:

golang go语言 http包 和 高并发下的websocket(golang 高并发http请求)

golang go语言 http包 和 高并发下的websocket(golang 高并发http请求)

总结

以上是小编为你收集整理的golang go语言 http包 和 高并发下的websocket全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

golang gorilla websocket例子

golang gorilla websocket例子

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

在golang语言中,目前有两种比较常用的实现方式:一个是golang自带的库,另一个是gorilla,功能强大。

golang自带库的使用例子可参考以前的博文:Golang如何使用websocket

本文以gorilla为例,介绍websocket的使用。

下载gorilla

# go get github.com/gorilla/websocket

下面例子中主要包括两部分,server和client。
client部分又包括:web client(浏览器)和非web client。

server

server端是一个HTTP 服务器,监听8080端口。

当接收到连接请求后,将连接使用的http协议升级为websocket协议。后续通信过程中,使用websocket进行通信。

对每个连接,server端等待读取数据,读到数据后,打印数据,然后,将数据又发送给client.

server启动方式

# go run server.go

server.go代码如下:

// copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

package main

import (
    "flag"
    "html/template"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

var addr = flag.String("addr","localhost:8080","http service address")

var upgrader = websocket.Upgrader{} // use default options

func echo(w http.ResponseWriter,r *http.Request) {
    c,err := upgrader.Upgrade(w,r,nil)
    if err != nil {
        log.Print("upgrade:",err)
        return
    }
    defer c.Close()
    for {
        mt,message,err := c.ReadMessage()
        if err != nil {
            log.Println("read:",err)
            break
        }
        log.Printf("recv: %s",message)
        err = c.WriteMessage(mt,message)
        if err != nil {
            log.Println("write:",err)
            break
        }
    }
}

func home(w http.ResponseWriter,r *http.Request) {
    homeTemplate.Execute(w,"ws://"+r.Host+"/echo")
}

func main() {
    flag.Parse()
    log.SetFlags(0)
    http.HandleFunc("/echo",echo)
    http.HandleFunc("/",home)
    log.Fatal(http.ListenAndServe(*addr,nil))
}

var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html>
<head>
<Meta charset="utf-8">
<script>  
window.addEventListener("load",function(evt) {
    var output = document.getElementById("output");
    var input = document.getElementById("input");
    var ws;
    var print = function(message) {
        var d = document.createElement("div");
        d.innerHTML = message;
        output.appendChild(d);
    };
    document.getElementById("open").onclick = function(evt) {
        if (ws) {
            return false;
        }
        ws = new WebSocket("{{.}}");
        ws.onopen = function(evt) {
            print("OPEN");
        }
        ws.onclose = function(evt) {
            print("CLOSE");
            ws = null;
        }
        ws.onmessage = function(evt) {
            print("RESPONSE: " + evt.data);
        }
        ws.onerror = function(evt) {
            print("ERROR: " + evt.data);
        }
        return false;
    };
    document.getElementById("send").onclick = function(evt) {
        if (!ws) {
            return false;
        }
        print("SEND: " + input.value);
        ws.send(input.value);
        return false;
    };
    document.getElementById("close").onclick = function(evt) {
        if (!ws) {
            return false;
        }
        ws.close();
        return false;
    };
});
</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<p>Click "Open" to create a connection to the server,"Send" to send a message to the server and "Close" to close the connection. 
You can change the message and send multiple times.
<p>
<form>
<button id="open">Open</button>
<button id="close">Close</button>
<p><input id="input" type="text" value="Hello World!">
<button id="send">Send</button>
</form>
</td><td valign="top" width="50%">
<div id="output"></div>
</td></tr></table>
</body>
</html>
`))

server output:

recv: 2018-10-20 17:09:12.497129965 +0800 CST m=+1.010137585
recv: 2018-10-20 17:09:13.495602484 +0800 CST m=+2.008641088
recv: 2018-10-20 17:09:14.49401062 +0800 CST m=+3.007080206
recv: 2018-10-20 17:09:15.497114615 +0800 CST m=+4.010215329
recv: 2018-10-20 17:09:16.494394706 +0800 CST m=+5.007526368
read: websocket: close 1000 (normal)

非web client

client启动后,首先连接server。

连接建立后,主routine每一秒钟向server发送消息(当前时间)。

另一个routine从server接收数据,并打印。

当client退出时,会向server发送关闭消息。接着,等待退出。

client启动方式

# go run client.go

client代码如下:

// copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

package main

import (
    "flag"
    "log"
    "net/url"
    "os"
    "os/signal"
    "time"

    "github.com/gorilla/websocket"
)

var addr = flag.String("addr","http service address")

func main() {
    flag.Parse()
    log.SetFlags(0)

    interrupt := make(chan os.Signal,1)
    signal.Notify(interrupt,os.Interrupt)

    u := url.URL{Scheme: "ws",Host: *addr,Path: "/echo"}
    log.Printf("connecting to %s",u.String())

    c,_,err := websocket.DefaultDialer.Dial(u.String(),nil)
    if err != nil {
        log.Fatal("dial:",err)
    }
    defer c.Close()

    done := make(chan struct{})

    go func() {
        defer close(done)
        for {
            _,err := c.ReadMessage()
            if err != nil {
                log.Println("read:",err)
                return
            }
            log.Printf("recv: %s",message)
        }
    }()

    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-done:
            return
        case t := <-ticker.C:
            err := c.WriteMessage(websocket.TextMessage,[]byte(t.String()))
            if err != nil {
                log.Println("write:",err)
                return
            }
        case <-interrupt:
            log.Println("interrupt")

            // Cleanly close the connection by sending a close message and then
            // waiting (with timeout) for the server to close the connection.
            err := c.WriteMessage(websocket.CloseMessage,websocket.FormatCloseMessage(websocket.ClosenormalClosure,""))
            if err != nil {
                log.Println("write close:",err)
                return
            }
            select {
            case <-done:
            case <-time.After(time.Second):
            }
            return
        }
    }
}

client output:

connecting to ws://localhost:8080/echo
recv: 2018-10-20 17:09:12.497129965 +0800 CST m=+1.010137585
recv: 2018-10-20 17:09:13.495602484 +0800 CST m=+2.008641088
recv: 2018-10-20 17:09:14.49401062 +0800 CST m=+3.007080206
recv: 2018-10-20 17:09:15.497114615 +0800 CST m=+4.010215329
recv: 2018-10-20 17:09:16.494394706 +0800 CST m=+5.007526368
^Cinterrupt
read: websocket: close 1000 (normal)

web client

web client,也就是使用浏览器。
在浏览器中输入http://127.0.0.1:8080

浏览器

"Open",然后"send"

server output:

recv: Hello World!!

参考

百度百科

https://baike.baidu.com/item/WebSocket

github

https://github.com/gorilla/websocket

doc

https://godoc.org/github.com/gorilla/websocket

example

https://github.com/gorilla/websocket/blob/master/examples/

Golang websocket

Golang websocket

环境:Win10 + Go1.9.2

1. 先下载并引用 golang 的 websocket 库

①golang 的官方库都在 https://github.com/golang 下,而 websocket 库在 /net 下。

②如果没有安装 Git,需要先安装 Git。

③使用 go get -u github.com/golang/net/websocket 下载代码,将安装在环境变量 GOPATH 配置的路径中。

代码中使用路径为 "golang.org/x/net/websocket",在对应路径下没有代码的话则引用出错,可将对应代码放在 GOPAHT/golang.org/x/net 下。

2. 服务端 Go 代码

package main

import (
    "fmt"
    "golang.org/x/net/websocket"
    "net/http"
    "os"
    "time"
)

//错误处理函数
func checkErr(err error, extra string) bool {
    if err != nil {
        formatStr := " Err : %s\n";
        if extra != "" {
            formatStr = extra + formatStr;
        }

        fmt.Fprintf(os.Stderr, formatStr, err.Error());
        return true;
    }

    return false;
}

func svrConnHandler(conn *websocket.Conn) {
    request := make([]byte, 128);
    defer conn.Close();
    for {
        readLen, err := conn.Read(request)
        if checkErr(err, "Read") {
            break;
        }

        //socket被关闭了
        if readLen == 0 {
            fmt.Println("Client connection close!");
            break;
        } else {
            //输出接收到的信息
            fmt.Println(string(request[:readLen]))

            time.Sleep(time.Second);
            //发送
            conn.Write([]byte("World !"));
        }

        request = make([]byte, 128);
    }
}

func main() {
    http.Handle("/echo", websocket.Handler(svrConnHandler));
    err := http.ListenAndServe(":6666", nil);
    checkErr(err, "ListenAndServe");
    fmt.Println("Func finish.");
}

 PS:《Golang socket》中使用了 go coroutine 来处理 connection 的消息阻塞接收,websocket 不需要进行这样的处理,否则将报 use of closed network connection 的错误!

 3.

①客户端 Go 代码

package main

import (
    "fmt"
    "golang.org/x/net/websocket"
    "os"
    "sync"
)

var gLocker sync.Mutex;    //全局锁
var gCondition *sync.Cond; //全局条件变量

var origin = "http://127.0.0.1:6666/"
var url = "ws://127.0.0.1:6666/echo"

//错误处理函数
func checkErr(err error, extra string) bool {
    if err != nil {
        formatStr := " Err : %s\n";
        if extra != "" {
            formatStr = extra + formatStr;
        }

        fmt.Fprintf(os.Stderr, formatStr, err.Error());
        return true;
    }

    return false;
}

//连接处理函数
func clientConnHandler(conn *websocket.Conn) {
    gLocker.Lock();
    defer gLocker.Unlock();
    defer conn.Close();
    request := make([]byte, 128);
    for {
        readLen, err := conn.Read(request)
        if checkErr(err, "Read") {
            gCondition.Signal();
            break;
        }

        //socket被关闭了
        if readLen == 0 {
            fmt.Println("Server connection close!");

            //条件变量同步通知
            gCondition.Signal();
            break;
        } else {
            //输出接收到的信息
            fmt.Println(string(request[:readLen]))

            //发送
            conn.Write([]byte("Hello !"));
        }

        request = make([]byte, 128);
    }
}

func main() {
    conn, err := websocket.Dial(url, "", origin);
    if checkErr(err, "Dial") {
        return;
    }

    gLocker.Lock();
    gCondition = sync.NewCond(&gLocker);
    _, err = conn.Write([]byte("Hello !"));
    go clientConnHandler(conn);

    //主线程阻塞,等待Singal结束
    for {
        //条件变量同步等待
        gCondition.Wait();
        break;
    }
    gLocker.Unlock();
    fmt.Println("Client finish.")
}

②如果客户端不使用 Go 代码,可以使用 Cocos Creator 的 js 代码

cc.Class({
    extends: cc.Component,

    properties: {

    },

    ctor: function () {
        this.ws = null;
    },

    onLoad: function () {
        var self = this;

        this.ws = new WebSocket("ws://127.0.0.1:6666/echo");
        this.ws.onopen = function (event) {

            console.log("Send Text WS was opened.");

            if (self.ws.readyState === WebSocket.OPEN) {
                self.ws.send("Hello !");
            }
            else{
                console.log("WebSocket instance wasn''t ready...");
            }
        };

        this.ws.onmessage = function (event) {
            console.log("response text msg: " + event.data);
            self.ws.send("Hello !");
        };

        this.ws.onerror = function (event) {
            console.log("Send Text fired an error");
        };

        this.ws.onclose = function (event) {
            console.log("WebSocket instance closed.");
        };

    },

    // called every frame
    update: function (dt) {

    },
});

golang websocket 入门

golang websocket 入门

我们先写一个最简单的go http服务

package main

import (
    "net/http"
)

func main() {
    http.HandleFunc("/",func(w http.ResponseWriter,r *http.Request) {
        w.Write([]byte("hello world"))
    })
    http.ListenAndServe(":9000",nil)
}

上面的太简单,就是一个http的服务,启动打开浏览器就可以输出hello world了,这是http,每次一个请求一个返回,虽然http的1.1版本已经支持keep-alive了,但如果想从服务发送到客户端,还是不行的,那么就诞生了websocket了。
现在改进一下代码:

package main

import (
    "net/http"
    "github.com/gorilla/websocket"
    "fmt"
)
var upgrade = websocket.Upgrader{}

func main() {
    http.HandleFunc("/",r *http.Request) {
        w.Write([]byte("hello world"))
    })

    http.HandleFunc("/v1/ws",r *http.Request) {
        conn,_ := upgrade.Upgrade(w,r,nil)
        go func(conn *websocket.Conn) {
            for{
                //mtype :TextMessage=1/BinaryMessage=-2/CloseMessage=8/PingMessage=9/PongMessage=10
                mtype,msg,_:=conn.ReadMessage()
                switch mtype {
                case 1:
                    conn.WriteMessage(mtype,msg)
                case 8:
                    fmt.Println("close")
                }
            }
        }(conn)

    })
    http.ListenAndServe(":9000",nil)
}

这个里面如果请求的是v1/ws的话就进入websocket的,就是把用户的输入当做输出,返回到客户端。下面通过浏览器console测试一下

var ws = new WebSocket("ws://127.0.0.1:9000/v1/ws")
ws.addEventListener("message",function(e){console.log(e);});
ws.send("123")

运行一下就可以看到效果。当然,如果你不想返回,只是在后端输出一下

mtype,_:=conn.ReadMessage()
fmt.Println(mtype,":",string(msg))

那么前端就收不到任何返回。

进一步,那么如何后端推送呢,

http.HandleFunc("/v1/ws",func(w http.ResponseWriter,r *http.Request) {
        conn,_ := upgrade.Upgrade(w,nil)
        go func(conn *websocket.Conn) {
            ch :=time.Tick(5*time.Second)
            for range ch{
                fmt.Println("call")
                conn.WriteMessage(1,[]byte("abc"))

            }
        }(conn)

    })

这样只要前端绑定了这个message就可以定时收到后端的推送了。但是如果前端关闭ws.close()将不会收到推送了。
在结束这篇blog之前还要补充一点就是服务关闭,如果前端关闭,后端任然继续读取数据将会报错panic: repeated read on Failed websocket connection。因为无法读取到客户端的数据了。所以还要在第一个例子的地方加上一个异常处理

mtype,err:=conn.ReadMessage()
    if err != nil{
        conn.Close()
        return
    }

第一篇入门就和大家分享到这来

Golang websocket使用方法

Golang websocket使用方法

package main

import (
	"fmt"
	"log"
	"net/http"

	"code.google.com/p/go.net/websocket"
)

func main() {
	http.Handle("/",websocket.Handler(Echo))
	if err := http.ListenAndServe(":1234",nil); err != nil {
		log.Fatal("ListenAndServer: ",err)
	}
}

func Echo(ws *websocket.Conn) {
	var err error

	for {
		var reply string
		if err = websocket.Message.Receive(ws,&reply); err != nil {
			fmt.Println("Can't receive")
			break
		}

		fmt.Println("Received back from client: ",reply)

		msg := "Received: " + reply
		fmt.Println("Sending to client" + msg)

		if err = websocket.Message.Send(ws,msg); err != nil {
			fmt.Println("Can't send")
			break
		}
	}
}

关于golang go语言 http包 和 高并发下的websocketgolang 高并发http请求的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于golang gorilla websocket例子、Golang websocket、golang websocket 入门、Golang websocket使用方法的相关知识,请在本站寻找。

本文标签: