클라이언트 연결을 닫은 후 TCP 소켓에서 버퍼링된 콘텐츠를 완전히 읽는 방법은 무엇입니까?

PHPz
풀어 주다: 2024-02-11 16:33:18
앞으로
451명이 탐색했습니다.

关闭客户端连接后如何从 tcp 套接字完全读取缓冲内容?

네트워크 프로그래밍에서는 클라이언트 연결을 닫은 후 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:stackoverflow.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!