我正在使用 websocket 服务器,由于某种原因它输出:
“WSARecv tcp 127.0.0.1:8080:使用关闭的网络连接。”
我不知道为什么会这样说,因为我在任何时候都没有关闭连接。
下面是服务器的一些源代码文件。如果需要,完整的源代码是 here on GitHub 。
连接.go
package net
import (
"log"
"golang.org/x/net/websocket"
pnet "kekocity/misc/packet"
"kekocity/interfaces"
)
type Connection struct {
socket *websocket.Conn
txChan chan pnet.INetMessageWriter
rxChan chan pnet.INetMessageReader
user interfaces.IUser
}
func NewConnection(_socket *websocket.Conn) *Connection {
// The pointer allow us to modify connection struct from outside
connection := &Connection{
socket: _socket,
txChan: make(chan pnet.INetMessageWriter),
rxChan: make(chan pnet.INetMessageReader),
}
go connection.ReceivePoller()
go connection.SendPoller()
return connection
}
func (c *Connection) AssignToUser(_user interfaces.IUser) {
if _user == nil {
panic("net.connection: the user interface can not be nil!")
return
}
c.user = _user
_user.SetNetworkChans(c.rxChan, c.txChan)
}
/*
* ReceivePoller and SendPoller starts listening when the first packet is verified and the new connection is started
*/
func (c *Connection) ReceivePoller() {
for {
packet := pnet.NewPacket()
var buffer []uint8
err := websocket.Message.Receive(c.socket, &buffer)
if err == nil {
copy(packet.Buffer[0:len(buffer)], buffer[0:len(buffer)])
c.parsePacket(packet)
} else {
println(err.Error())
break
}
}
}
func (c *Connection) SendPoller() {
for {
// Read messages from transmit channel
message := <-c.txChan
if message == nil {
log.Println("SenPoller", "The message is nil, break the loop")
break
}
// Convert netmessage to packet
packet := message.WritePacket()
packet.SetHeader()
// Create byte buffer
buffer := packet.GetBuffer()
data := buffer[0:packet.GetMsgSize()]
// Send bytes off to the internetz
websocket.Message.Send(c.socket, data)
}
}
func (c *Connection) parsePacket(_packet pnet.IPacket) {
log.Println("net.connection:", "Received new packet!")
}
func (c *Connection) Close() {
// Close channels
close(c.txChan)
close(c.rxChan)
// Close the socket
c.socket.Close()
c.user = nil
}
服务器.go
package net
// <imports>
import (
"log"
"fmt"
"net/http"
"golang.org/x/net/websocket"
pnet "kekocity/misc/packet"
cmap "kekocity/misc/concurrentmap"
"kekocity/data/helpers"
"kekocity/net/message"
)
var server *Server
type Server struct {
port int
connectedUsers *cmap.ConcurrentMap
}
func init() {
server = newServer()
}
func newServer() *Server {
return &Server{
port: 8080,
connectedUsers: cmap.New(),
}
}
func Listen(_port int) {
server.port = _port
log.Printf("Listening for connections on port %d!", _port)
http.Handle("/ws", websocket.Handler(clientConnection))
err := http.ListenAndServe(fmt.Sprintf(":%d", _port), nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
func clientConnection(clientsock *websocket.Conn) {
packet := pnet.NewPacket()
buffer := make([]uint8, pnet.PACKET_MAXSIZE)
recv, err := clientsock.Read(buffer)
if err == nil {
copy(packet.Buffer[0:recv], buffer[0:recv])
parseFirstMessage(clientsock, packet)
} else {
if err.Error() != "EOF" {
log.Println("net.server", "Client connection error:", err.Error())
}
}
}
func parseFirstMessage(_conn *websocket.Conn, _packet *pnet.Packet) {
_message := _packet.ToString()
// If the first packet length is < 1 close the socket
if len(_message) < 1 {
_conn.Close()
return
}
// Create the connection
connection := NewConnection(_conn)
// Authentication wrapper
authPacket := &message.AuthMessage{}
user, err := helpers.AuthHelper.AuthenticateUsingCredentials(_message)
if err != nil {
log.Fatal("Invalid credentials!")
authPacket.Status = "error"
} else {
// Need to check if its already logged
authPacket.Status = "success"
connection.AssignToUser(user)
connection.txChan <- authPacket
return
}
// Send bad auth message and close
connection.txChan <- authPacket
connection.Close()
}
完整源代码: github
处理程序完成后立即取消请求中的上下文。
这就是为什么你的上下文。在此图中,您可以找到如何在
server.Serve
方法中创建上下文。博客文章中对其进行了更详细的描述: HTTP context livetime 。
在 websocket 中,情况非常相似。处理程序完成后,上下文立即关闭。
要解决这个问题,您可以从
context.Background()
创建一个新的上下文,如果需要,添加一些超时并改用它。