네트워크 프로그래밍에서는 클라이언트 연결을 닫은 후 TCP 소켓에서 버퍼링된 콘텐츠를 완전히 읽는 방법이 일반적인 문제입니다. 클라이언트가 연결을 닫아도 서버 측에는 읽지 않은 데이터가 남아 있을 수 있습니다. 버퍼 내용을 완전히 읽으려면 다음 방법을 사용할 수 있습니다. 1. 데이터 끝 플래그를 읽을 때까지 루프 읽기를 사용합니다. 2. 데이터가 읽히지 않으면 타임아웃을 설정하고 루프에서 빠져나옵니다. 3. Non-Blocking 소켓을 사용하여 읽을 데이터가 있는지 폴링하여 확인합니다. 위의 방법을 사용하면 TCP 소켓에서 버퍼 내용을 완전히 읽을 수 있으므로 네트워크 통신의 안정성과 신뢰성이 향상됩니다.
TCP 소켓을 수신하는 Go 서버가 있는데, 종료하는 동안 클라이언트에게 더 많은 데이터 전송을 중지하고 클라이언트가 지금까지 보낸 모든 내용을 읽도록 지시하고 싶습니다. 내가 본 것은 클라이언트 연결이 닫히면 서버가 읽기를 중지하지만 클라이언트가 보낸 것으로 생각되는 모든 것을 결코 수신하지 못한다는 것입니다. 제가 생각하는 현상은 운영 체제가 수신된 TCP 패킷을 버퍼링한 다음 서버가 클라이언트 연결을 닫을 때 해당 패킷을 폐기한다는 것입니다.
여기 문제를 보여주는 프로그램이 있습니다. 서버는 수신한 내용을 듣고 인쇄합니다. 클라이언트가 보낸 내용을 인쇄합니다. 서버는 클라이언트를 중단하여 중지하지만 결국에는 두 목록이 동일해지기를 원합니다.
이 예에서는 bufio.scanner를 사용하여 소켓을 읽었지만 연결에서 바이트 읽기만 시도했지만 동일한 결과를 얻었습니다.
conn.(*net.tcpconn).closewrite()
정확히 내가 원하는 것처럼 들리지만 이것이 클라이언트를 전혀 손상시키지 않는 것 같습니다.
conn.(*net.tcpconn).setreadbuffer(0)
- 이것도 시도해 보았지만 0은 허용되는 값이 아닙니다(패닉).
내 컴퓨터의 출력은 다음과 같습니다.
package main import ( "bufio" "fmt" "net" "strconv" "sync" "time" ) const port = ":8888" var wg sync.waitgroup func main() { wg.add(1) go func() { // wait for the server to start time.sleep(1000 * time.millisecond) client() }() // server listens wg.add(1) server() wg.wait() } func server() { defer wg.done() listener, err := net.listen("tcp", port) if err != nil { panic(err) } received := make([]string, 0) conn, err := listener.accept() if err != nil { panic(err) } defer conn.close() scanner := bufio.newscanner(conn) for i := 0; scanner.scan(); i++ { received = append(received, scanner.text()) // arbitrary condition: simulate a server shutdown - interrupt the client if len(received) == 2 { _ = conn.(*net.tcpconn).close() } } fmt.println("server received: ", received) } func client() { defer wg.done() conn, err := net.dial("tcp", port) if err != nil { panic(err) } sent := make([]string, 0) defer conn.close() for i := 0; i < 50000; i++ { v := strconv.itoa(i) _, err := conn.write([]byte(v + "\n")) if err != nil { fmt.println("client interrupted:", err) break } else { sent = append(sent, v) // slow down the sends to make output readable //time.sleep(1 * time.millisecond) } } fmt.println("client sent: ", sent) }
TCP는 고유한 의미 없이 안정적인 양방향 바이트 스트림만 제공합니다. 서버가 클라이언트가 더 이상 데이터를 보내지 말아야 한다는 신호를 보내도록 하려면 TCP가 제공하는 순수 데이터 전송 위의 계층인 애플리케이션 프로토콜의 일부로 이 기능을 구현해야 합니다.
위 내용은 클라이언트 연결을 닫은 후 TCP 소켓에서 버퍼링된 콘텐츠를 완전히 읽는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!