simple-chatroom icon indicating copy to clipboard operation
simple-chatroom copied to clipboard

conn 放入 client 的里面去读会有问题

Open fredGmm opened this issue 6 years ago • 6 comments

client方法里面使用conn链接readjson会出现 use of closed network connection和 读取消息为空的问题。

fredGmm avatar Jun 26 '19 09:06 fredGmm

能描述一下具体出现问题的条件吗?

LinkinStars avatar Jun 27 '19 00:06 LinkinStars

我将我的代码主要相关的部分移到了一个文件,以便来查找相关问题。如下: `package main

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

var upgrader = websocket.Upgrader{}

type Client struct { UserId string Connection *websocket.Conn Send chan Message } type Message struct { //Username string json:"username" Message string json:"message" ToUserId string json:"to_user_id" UserId string json:"user_id" GroupId string json:"group_id" }

func main() { http.HandleFunc("/", NewConn) err := http.ListenAndServe("192.168.0.103:3000", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } }

// 新建连接 func NewConn(w http.ResponseWriter, r *http.Request) { //不检查来源 upgrader.CheckOrigin = func(r *http.Request) bool { return true } ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Print("https升级为wss失败:err:") log.Fatal(err) } userId := r.URL.Query().Get("id") // 用户id

defer func() {
	err := ws.Close()
	if err != nil {
		fmt.Println("链接时 断开:")
		fmt.Println(userId)
		fmt.Println(err)
		// 发送消息通知
		return
	}
}()
//链接
if len(userId) > 0 && userId != "0" {
	client := module.NewClient(ws, userId)
	go client.ReadMessage()
	go client.WriteMessage()

	//for {
	//	msg := module.Message{}
	//	err := ws.ReadJSON(&msg)
	//	if err != nil {
	//		log.Print("这个ws读取消息时错误,将连接移除")
	//		log.Print(userId)
	//		log.Print(err)
	//		return
	//	}
	//	log.Print(msg)
	//}

}

}

func NewClient(conn *websocket.Conn, userId string) *Client { return &Client{ UserId: userId, Connection: conn, Send: make(chan Message), } }

func (c *Client) ReadMessage() { for { msg := Message{} err := c.Connection.ReadJSON(&msg) log.Print(msg) log.Print(c.Connection) if err != nil { log.Print("这个ws读取消息时错误,将连接移除") log.Print(err) } }

}

func (c *Client) WriteMessage() { for { msg := <-c.Send // 发送消息给 链接 if err := c.Connection.WriteJSON(msg); err != nil { log.Print("关闭链接") log.Print(err) err := c.Connection.Close() if err != nil { log.Print("写消息时关闭链接失败") log.Print(err) } } } } ` 我把 启动协程去读取消息 改为在当前环境直接读取就没问题了,我今天在找寻其中的原因。 如果你能发现其中的问题,希望能告知,谢谢~~

fredGmm avatar Jun 27 '19 02:06 fredGmm

格式调整了 上传还是有点乱,可以直接复制到ide运行哈

fredGmm avatar Jun 27 '19 02:06 fredGmm

原来是这样。。。 image 你这段代码如果使用协程去处理那么 go client.ReadMessage() go client.WriteMessage() 这两句走完之后是不会阻塞的,会直接走到defer func从而将连接关闭,就会出现问题;而当你使用for去处理的时候,被阻塞了,一直在循环,所以不会被关闭,所以就没有问题

LinkinStars avatar Jun 27 '19 02:06 LinkinStars

难怪,我刚刚把后面逻辑的group <- client 加上好像好了,应该主协程退出的原因。 非常谢谢你,希望能加你一个联系方式。如此低级的问题浪费你时间了~我微-信:hb824871515

fredGmm avatar Jun 27 '19 02:06 fredGmm

没事,小问题

LinkinStars avatar Jun 27 '19 03:06 LinkinStars