2013-08-14 2 views
0

Go에서 간단한 콘솔 채팅을하려고하는데, 연습하기 만하면됩니다. 그러나 서버에서 메시지를 다시 보내는 방법을 모르겠습니다. 서버는 메시지를 수신 한 다음 연결을 닫습니다. 어떻게 응답 할 수 있습니까?Go의 양방향 연결

나는 웹 소켓에 관한 정보를 찾고 있었지만 브라우저와 상호 작용하는 데 사용된다고 생각합니다.

func runServer() { 
    // Listen on a port 
    listen, error := net.Listen("tcp", ":8272") 

    // Handles eventual errors 
    if error != nil { 
     fmt.Println(error) 
     return 
    } 

    fmt.Println("Listening in port 8272.") 

    for { 
     // Accepts connections 
     con, error := listen.Accept() 

     // Handles eventual errors 
     if error != nil { 
      fmt.Println(error) 
      continue 
     } 

     fmt.Println("Connection accepted.") 

     // Handles the connection 
     go handleConnection(con) 
    } 
} 

func handleConnection(con net.Conn) { 
    fmt.Println("Handling connection.") 

    var message string 

    // Decodes the received message 
    decoder := gob.NewDecoder(con) 
    error := decoder.Decode(&message) 

    // Checks for errors 
    if error != nil { 
     fmt.Println(error) 
    } else { 
     fmt.Println("Received", message) 
    } 

    // Closes the connection 
    con.Close() 
    fmt.Println("Connection closed.") 
} 

이 클라이언트의 기능입니다 : 사전에

func runClient() { 
    // Connects to server 
    con, error := net.Dial("tcp", "127.0.0.1:8272") 

    // Handles eventual errors 
    if error != nil { 
     fmt.Println(error) 
     return 
    } 

    fmt.Println("Connected to 127.0.0.1:8272.") 

    // Sends a message 
    message := "Hello world" 
    encoder := gob.NewEncoder(con) 
    error = encoder.Encode(message) 

    // Checks for errors 
    if error != nil { 
     fmt.Println(error) 
    } 

    con.Close() 

    fmt.Println("Message sent. Connection closed.") 
} 

감사

이 서버의 두 가지 기능입니다.

+0

을)'또는 적어도 당신이 연결을 완료하면 자리로 이동 좋은 시작이 될 것입니다 ... – geoffspear

+0

그러나 응답을 기다리기 위해 어떤 방법을 사용해야합니까? – aochagavia

답변

3

con 개체는 여기에 설명 된 ReadWrite 메서드가있는 연결입니다. here. 연결을 반복하고 수신 데이터 Read을 시도한 다음 처리하고 (아마도) Write 서버 응답을 다시 보내야합니다. 만 처리

go func(c net.Conn) { 
    // Echo all incoming data. 
    io.Copy(c, c) 
    // Shut down the connection. 
    c.Close() 
}(conn) 

:

문서는 example 작은을 보여줍니다 (여기서, bufferio 패키지 등이 좀 더 편리한 방법으로 처리 할 수 ​​있습니다, 이것은 단지 낮은 수준의 ReadWriter 인터페이스) 첫 번째 메시지를 닫은 다음 닫습니다. 귀하의 예제는이 같은 것, 그래서

go func(c net.Conn) { 
    // Infinite loop: Get data, copy them and start over 
    for { 
     // Echo all incoming data. 
     io.Copy(c, c) 
    } 
    // Shut down the connection. 
    c.Close() 
}(conn) 

물론 서버와 관련된 무엇이든 함께 io.Copy 교체 : 또한

func handleConnection(con net.Conn) { 
    fmt.Println("Handling connection.") 

    defer func() { 
     // Closes the connection 
     con.Close() 
     fmt.Println("Connection closed.") 
    }() 

    var message string 

    // Decodes the received message 
    decoder := gob.NewDecoder(con) 
    encoder := gob.NewEncoder(con) 
    for { 
     error := decoder.Decode(&message) 

     // Checks for errors 
     if error != nil { 
      fmt.Println(error) 
      // Exit the loop 
      return 
     } else { 
      fmt.Println("Received", message) 
      // Sending back 
      if error = encoder.Encode(message); error != nil { 
       fmt.Println(error) 
       return 
      } else { 
       fmt.Println("Echo'd successfuly ! Waiting for next message...") 
      } 
     } 
    } 
} 

당신은 아마 사용해야합니다, 당신은이 같은 각각의 수신 메시지를 처리 ​​할 수 ​​있습니다 로깅 메시지에는 fmt 대신 log 패키지가 필요합니다 (그러나 여기서는 관련이 없습니다).

모든 작동 방식을 이해하려면 기본 http 서버 here의 구현을 찾아 보는 것이 좋습니다.

마찬가지로, 클라이언트는 루프 같은 패턴을 사용해야`con.Close를 (제거

LOOP: 
    Send data (e.g. encoder.Encode) 
    Receive data (e.g. decoder.Decode) 
    if problem or termination -> break out of loop 
END 
close connection