我正在試驗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