저는 TCP가 어떻게 작동하는지 이해하려고 노력하고 있으며 지금까지 제가 아는 것은 "무작위" 연결 끊김이 발생하면 한쪽이 다른 쪽이 아직 살아 있는지 알 수 없다는 것뿐입니다. 이것이 일부 PING/PONG 알고리즘이나 TCP 연결 유지가 사용되는 이유입니다. 클라이언트가 서버에 연결하고 10초 후에 간단한 메시지를 보내는 간단한 클라이언트-서버 애플리케이션을 만들었습니다. 나를 혼란스럽게 하는 것은 다음 두 가지 경우에 클라이언트가 더 이상 존재하지 않는다는 것을 서버가 어떻게 아는가입니다.
Error Reading: read tcp 127.0.0.1:8080->127.0.0.1:60845 : wsarecv: 现有连接被远程主机强行关闭.
(다시 말하지만, 클라이언트가 더 이상 존재하지 않는다는 것을 어떻게 아는지 모르겠습니다.) 운영 체제(또는 golang net
라이브러리)가 관련되어 있고 TCP 연결이 실제로 닫히기 전에 추가 메시지나 유사한 메시지를 보내 이 상황을 처리한다고 가정합니다.
어떤 도움이라도 환영합니다. 다음은 로컬 또는 온라인 Go Playground에서 실행할 수 있도록 제가 사용한 전체 코드입니다.
client.go
으아악server.go
package main import ( "fmt" "net" "time" ) func main() { // Connect to the server conn, err := net.Dial("tcp", "localhost:8080") if err != nil { fmt.Println("Error connecting:", err) return } defer conn.Close() // Send a message to the server message := "Hello from client!" time.Sleep(10000 * time.Millisecond) conn.Write([]byte(message)) // Read the response from the server buffer := make([]byte, 1024) n, err := conn.Read(buffer) if err != nil { fmt.Println("Error reading:", err) return } // Print the server's response fmt.Printf("Received response from server: %s\n", buffer[:n]) }
제가 잘 모르는 내용을 얘기하고 있다는 걸 깨닫고 직접 테스트해봤습니다. 동일한 기계에 있는 세 개의 별도 터미널에 있는 장난감 예:
감독: sudo tcpdump -tttt -i lo port 8887
(您可能需要找出您的本地主机设备是什么,也许是 lo0
,使用 sudo tcpdump -D
。观察 Flags 字段:.
ACK이고 나머지는 설명이 필요합니다. )
서버:nc -l 8887
클라이언트:nc localhost 8887
클라이언트를 입력하고 Enter를 누르세요
서버를 입력하고 Enter를 누르세요
a) ctrl-c 또는 sigkill을 통해 클라이언트를 중지합니다.
b) 서버 중지:
그런 다음 클라이언트를 중지합니다.
이 실험은 WSL/Ubuntu에서 완료되었습니다. 아직 프로그램을 컴파일하지 않았지만 시나리오를 직접 테스트할 수 있습니다. 나를 놀라게 한 한 가지는 클라이언트 프로세스를 서명했음에도 불구하고 FIN이 여전히 전송된다는 것입니다. 이는 클라이언트 프로세스가 열린 포트로 종료되면 FIN을 보내는 것이 커널의 책임임을 나타냅니다. 또한 서버 측 프로세스가 중지되면 FIN이 전송되지 않아 클라이언트에서 RST 응답을 받게 됩니다.
TCP 프로토콜의 커널 구현이 이를 처리합니다. conn.Close()
에서 일어나는 일과는 별개로 이는 Go와 전혀 관련이 없습니다.
위 내용은 서버는 클라이언트가 더 이상 존재하지 않는다는 것을 어떻게 알 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!