我正在试验Go--并且想创建一个可以telnet到的TCP服务器,发送命令并接收响应。在Golang服务器中接受一个持久的tcp连接
const (
CONN_HOST = "localhost"
CONN_PORT = "3333"
CONN_TYPE = "tcp"
)
func main() {
listener, err := net.Listen(CONN_TYPE, fmt.Sprintf("%s:%s", CONN_HOST, CONN_PORT))
if err != nil {
log.Panicln(err)
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
log.Panicln(err)
}
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
buffer := make([]byte, 1024)
length, err := conn.Read(buffer)
if err != nil {
log.Panicln(err)
}
str := string(buffer[:length])
fmt.Println(conn.RemoteAddr().String())
fmt.Printf("Received command %d\t:%s\n", length, str)
switch str {
case "PING\r\n":
sendResponse("PONG", conn)
case "PUSH\r\n":
sendResponse("GOT PUSH", conn)
default:
conn.Write([]byte(fmt.Sprintf("UNKNOWN_COMMAND: %s\n", str)))
}
conn.Close() // closes the connection
}
func sendResponse(res string, conn net.Conn) {
conn.Write([]byte(res+"\n"))
}
上面的代码将每次关闭连接,踢我离开终端会话。但是我真正想要的是能够保持连接打开以进行更多的I/O操作。如果我只是删除conn.Close()
,那么服务器似乎挂在某个地方,因为它没有得到任何更多的响应。
我解决这个问题的方式是让我的handleRequest方法无休止地循环,以便它永远不会退出,直到它收到QUIT\r\n
消息。这是否合适 - 还是有更好的实现方式?
func handleRequest(conn net.Conn) {
for {
log.Println("Handling Request")
buffer := make([]byte, 1024)
length, err := conn.Read(buffer)
if err != nil {
log.Panicln(err)
}
str := string(buffer[:length])
fmt.Println(conn.RemoteAddr().String())
fmt.Printf("Received command %d\t:%s\n", length, str)
switch str {
case "PING\r\n":
sendResponse("PONG", conn)
case "PUSH\r\n":
sendResponse("GOT PUSH", conn)
case "QUIT\r\n":
sendResponse("Goodbye", conn)
conn.Close()
default:
conn.Write([]byte(fmt.Sprintf("UNKNOWN_COMMAND: %s\n", str)))
}
}
}
是的,你需要循环读取多次读取。不要惊慌失措,如果连接关闭,没有理由让程序崩溃。 – JimB
我认为这是正确的实施。只是一个提示:在你调用'conn.Close()'remeber调用break语句之后,否则for循环将永远运行 – Tinwor
JimB Thanks。重新犯错误 - 我只是在开发中,因为我还没有建立适当的错误处理程序。只是想捕捉错误。 Tinwor - 很好的地方。 – Gravy