Golangはwebsocket通信、gorilla/websocketを使用

4316 ワード

ケース:gorilla/websocketを使用してチャットルーム機能を実現
目次:
1、構想分析
2、コアコード
3、すべてのコード
4、テストコード
5、連絡して
一、構想分析
Websocketはhttpのアップグレードバージョンと理解すればよい
すべてのユーザをオブジェクトUserとして抽象化し、Userには1つの接続と1つのメッセージチャネルを含むべきである.
データプロセッサHub:あるユーザに送信されたデータを取得して各ユーザにプッシュする
二、実現&コアコード
Userの定義:
type User struct {
	conn *websocket.Conn
	msg  chan []byte
}

データ・プロセッサの定義:
type Hub struct {
	//    ,      
	userList map[*User]bool
	//  chan,        chan 
	register chan *User
	//  chan,        chan ,  map   
	unregister chan *User
	//    ,          
	broadcast chan []byte
}

データプロセッサの処理方法:
//            
func (h *Hub) run() {
	for {
		select {
		//   chan    
		case user := 

Websocketプロモーターを定義するには、次の手順に従います.
//       ,    http     websocket  
var up = &websocket.Upgrader{
	//         
	WriteBufferSize: 1024,
	ReadBufferSize:  1024,
	//    
	CheckOrigin: func(r *http.Request) bool {
		//    get  ,    
		if r.Method != "GET" {
			fmt.Println("      ")
			return false
		}
		//        chat,    
		if r.URL.Path != "/chat" {
			fmt.Println("      ")
			return false
		}
		//               
		return true
	},
}

ユーザーがサービスに接続するコールバック関数:ユーザーの読み書き操作を処理する
func wsHandle(w http.ResponseWriter, r *http.Request) {
	//             
	conn, err := up.Upgrade(w, r, nil)
	if err != nil {
		fmt.Println("      :", err)
		return
	}
	//         
	user := &User{
		conn: conn,
		msg:  make(chan []byte),
	}
	hub.register 

イニシエータ:
func main() {
	//       
	go hub.run()
	http.HandleFunc("/chat", wsHandle)         // chat    wshandle  
	http.ListenAndServe("127.0.0.1:8888", nil) //    
}

三、完全なコード、1つのserver.goファイル、情況によって自分で分割することができます
package main

import (
	"fmt"
	"github.com/gorilla/websocket"
	"net/http"
)

func main() {
	//       
	go hub.run()
	http.HandleFunc("/chat", wsHandle)         // chat    wshandle  
	http.ListenAndServe("127.0.0.1:8888", nil) //    
}

//    websocket   ,           
type Hub struct {
	//    ,      
	userList map[*User]bool
	//  chan,        chan 
	register chan *User
	//  chan,        chan ,  map   
	unregister chan *User
	//    ,          
	broadcast chan []byte
}

//    websocket    ,            
type User struct {
	conn *websocket.Conn
	msg  chan []byte
}

//       ,    http     websocket  
var up = &websocket.Upgrader{
	//         
	WriteBufferSize: 1024,
	ReadBufferSize:  1024,
	//    
	CheckOrigin: func(r *http.Request) bool {
		//    get  ,    
		if r.Method != "GET" {
			fmt.Println("      ")
			return false
		}
		//        chat,    
		if r.URL.Path != "/chat" {
			fmt.Println("      ")
			return false
		}
		//               
		return true
	},
}
//       ,    
var hub = &Hub{
	userList:   make(map[*User]bool),
	register:   make(chan *User),
	unregister: make(chan *User),
	broadcast:  make(chan []byte),
}

func wsHandle(w http.ResponseWriter, r *http.Request) {
	//             
	conn, err := up.Upgrade(w, r, nil)
	if err != nil {
		fmt.Println("      :", err)
		return
	}
	//         
	user := &User{
		conn: conn,
		msg:  make(chan []byte),
	}
	hub.register 

四、テストコード、goで作成した1つのクライアントを使用して、複数のユーザーをシミュレートする
package main

import (
	"bufio"
	"fmt"
	"github.com/gorilla/websocket"
	"io"
	"os"
	"sync"
)

var wg sync.WaitGroup

func main() {
	conn, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8888/chat", nil)
	if err != nil {
		fmt.Println("    :", err)
	}
	wg.Add(2)
	go read(conn)
	go writeM(conn)
	wg.Wait()
}
func read(conn *websocket.Conn) {
	defer wg.Done()
	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			fmt.Println("    :", err)
			break
		}
		if err == io.EOF {
			continue
		}
		fmt.Println("      :", string(msg))
	}
}
func writeM(conn *websocket.Conn) {
	defer wg.Done()
	for {
		fmt.Print("   :")
		reader := bufio.NewReader(os.Stdin)
		data, _ := reader.ReadString('
') conn.WriteMessage(1, []byte(data)) } }

五、作者接続方式:QQ 535495438