go web 之socket 和 websocket 学习 - Go语言中文社区

go web 之socket 和 websocket 学习


socket 介绍

socket 是客户端和服务器连接的桥梁,socket 用于web浏览器和服务器的通信,socket是一种文件描述符。
socket 分为两种 流式socket数据报式socket
1. 流式socket是一种面向连接的Socket,针对于面向连接的TCP服务应用
2. 数据报式socket是一种无连接的socket,对应于无连接的UDP服务应用

socket通信

socket 的通信依赖于三个部分IP端口协议, 这三部分可以标志一个进程
网络层的“ip地址”可以唯一标识网络中的主机,
而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。
这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中需要互相通信的进程,就可以利用这个标志在他们之间进行交互。

go 服务端的简单实现

package main

import (
    "net"
    "os"
    "fmt"
    "time"
)

func main() {
    service :=":7077"
    // 获得tcpAdd ,其中包括ip 和端口
    /*
    type TCPAddr struct {
    IP IP
    Port int
    }*/
    tcpAddr,err := net.ResolveTCPAddr("tcp4",service)
    checkerror(err)
    //监听端口号
    listener,err:=net.ListenTCP("tcp",tcpAddr)
    checkerror(err)
    for {
        //通过Accept接受连接
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        //使用goroutine 处理一个连接,实现并发
        go handleClient(conn)
    }
}

func handleClient(conn net.Conn){
    defer conn.Close()
    daytime:= time.Now().String()
    conn.Write([]byte(daytime))
}
func checkerror(err error)  {
    if err != nil{
         fmt.Fprintf(os.Stderr,"error: %s",err)
         os.Exit(1)
    }
}

websocket简介

WebSocket是HTML5的重要特性,它实现了基于浏览器的远程socket,它使浏览器和服务器可以进行全双工通信,许多浏览器(Firefox、Google Chrome和Safari)都已对此做了支持。

在WebSocket出现之前,为了实现即时通信,采用的技术都是“轮询”(见socket代码),即在特定的时间间隔内,由浏览器对服务器发出HTTP Request,服务器在收到请求后,返回最新的数据给浏览器刷新,“轮询”使得浏览器需要对服务器不断发出请求,这样会占用大量带宽。

WebSocket的协议颇为简单,在第一次handshake通过以后,连接便建立成功,其后的通讯数据都是以”x00″开头,以”xFF”结尾。在客户端,这个是透明的,WebSocket组件会自动将原始数据“掐头去尾”。

浏览器发出WebSocket连接请求,然后服务器发出回应,然后连接建立成功,这个过程通常称为“握手” (handshaking)。请看下面的请求和反馈信息:
HTTP信息

// 告诉服务器,发起的是websocket 请求
Upgrade: websocket
Connection: Upgrade

Sec-WebSocket-Key 是经过base64编码后的数据,是浏览器随机生成的

服务器端接收到这个请求之后需要把这个字符串连接上一个固定的字符串:

258EAFA5-E914-47DA-95CA-C5AB0DC85B11

即:f7cb4ezEAl6C3wRaU6JORA==连接上那一串固定字符串,生成一个这样的字符串:

f7cb4ezEAl6C3wRaU6JORA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

对该字符串先用 sha1安全散列算法计算出二进制的值,然后用base64对其进行编码,即可以得到握手后的字符串:

rE91AJhfC+6JdVcVXOGJEADEJdQ=

将之作为响应头Sec-WebSocket-Accept的值反馈给客户端。

简单例子

客户端

<html>
<head></head>
<body>
    <script type="text/javascript">
        var sock = null;
        var wsuri = "ws://127.0.0.1:1234";

        window.onload = function() {

            console.log("onload");

            sock = new WebSocket(wsuri);

            sock.onopen = function() {
                console.log("connected to " + wsuri);
            }

            sock.onclose = function(e) {
                console.log("connection closed (" + e.code + ")");
            }

            sock.onmessage = function(e) {
                console.log("message received: " + e.data);
            }
        };

        function send() {
            var msg = document.getElementById('message').value;
            sock.send(msg);
        };
    </script>
    <h1>WebSocket Echo Test</h1>
    <form>
        <p>
            Message: <input id="message" type="text" value="Hello, world!">
        </p>
    </form>
    <button onclick="send();">Send Message</button>
</body>
</html>

服务端:

package main

import (
    "code.google.com/p/go.net/websocket"
    "fmt"
    "log"
    "net/http"
)

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
        }
    }
}

func main() {
    http.Handle("/", websocket.Handler(Echo))

    if err := http.ListenAndServe(":1234", nil); err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

至此一个简单的websocket就实现了,

socket 和 websocket 比较

socket 基于HTTP , 客户端和服务器完成一次请求和处理后即断开连接。
通过for 轮询,不断地建立HTTP连接,然后处理。
websocket 最大的特点就是客户端可以主动向服务端发送信息。
并且websocket是基于HTTP的持久连接。只需要经过一次HTTP请求,就可以做到源源不断的信息传送了

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/MrJavaweb/article/details/79718573
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-09-04 15:50:30
  • 阅读 ( 1054 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢