서버가 데이터를 다시 보내지 않을 때 `socket.recv()`가 정지되는 이유는 무엇입니까?

Patricia Arquette
풀어 주다: 2024-11-22 22:33:26
원래의
846명이 탐색했습니다.

Why Does `socket.recv()` Stall When the Server Doesn't Send Data Back?

소켓 동작 이해: 데이터 전송 없이 Socket.recv()가 중단되는 이유

Python 소켓은 TCP 연결과 마찬가지로 데이터 스트림으로 동작합니다. 클라이언트와 서버 사이를 흐르는 것입니다. 이 글에서는 데이터 전송이 수정된 후 소켓.recv() 호출이 데이터를 반환하지 못하는 문제의 원인을 살펴봅니다.

Echo 서버 예제

공식 문서의 Python 에코 서버 예제를 고려해보세요. 이 서버는 들어오는 연결을 수신하고 데이터를 수신하여 클라이언트에 다시 보냅니다. 다음 코드 조각은 원래 서버 동작을 복제합니다.

import socket

HOST = ''
PORT = 50007 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print('Connected by', addr)

while True:
    data = conn.recv(1024)
    if not data: break
    conn.sendall(data)
conn.close()
로그인 후 복사

서버 동작 변경

클라이언트에 데이터를 다시 보내지 않도록 코드를 수정하면 문제가 발생합니다. :

while True:
    data = conn.recv(1024)
    if not data: break
conn.close()
로그인 후 복사

이 수정된 코드에서 while 루프는 클라이언트로부터 끝없이 데이터를 수신하지만, 서버는 데이터를 다시 보내지 않습니다. 이로 인해 클라이언트는 소켓.recv() 호출 시 무기한 정지됩니다.

통신 흐름 이해

TCP 소켓은 일대일 관계를 유지하지 않습니다. 서로 다른 끝점에서 호출을 보내고 받는 사이. 대신 프로토콜은 통신 규칙을 정의합니다. 이 경우 원래 에코 서버는 클라이언트가 연결을 끊을 때까지 서버가 수신된 데이터를 다시 에코하는 규칙을 구현했습니다.

서버 동작이 변경되면 규칙이 효과적으로 수정된 것입니다. 이제 서버는 데이터만 수신하고 클라이언트가 연결을 닫을 때까지 이를 버립니다. 서버는 절대로 클라이언트에 데이터를 다시 보내지 않습니다.

클라이언트 동작 조정

수정된 서버로 작업하려면 클라이언트가 해당 동작을 조정해야 합니다. 서버가 더 이상 적극적으로 데이터를 보내지 않기 때문에 클라이언트는 데이터를 다시 수신하면 연결이 완료되었음을 의미한다고 가정합니다. 이를 용이하게 하기 위해 클라이언트는 연결의 나가는 쪽을 닫아 서버에 데이터 전송이 완료되었음을 알려야 합니다. 그런 다음 클라이언트는 여러 개의 수신 호출을 수행하여 수신 데이터의 잠재적 조각화를 처리할 수 있습니다.

업데이트된 코드

아래는 서버와 클라이언트 모두에 대한 업데이트된 코드입니다. 수정된 규칙을 준수합니다. 통신:

서버:

import socket

HOST = ''
PORT = 50007 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print('Connected by', addr)

while True:
    data = conn.recv(1024)
    if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()
로그인 후 복사

클라이언트:

import socket

HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
s.shutdown(socket.SHUT_WR)
data = b''
while True:
    buf = s.recv(1024)
    if not buf:
        break
    data += buf
s.close()
print('Received', repr(data))
로그인 후 복사

스트림 기반 특성을 이해함으로써 TCP 소켓을 사용하고 그에 따라 통신 규칙을 조정하면 데이터가 생성되지 않고 소켓.recv()가 멈추는 문제를 해결할 수 있습니다. 보냈습니다.

위 내용은 서버가 데이터를 다시 보내지 않을 때 `socket.recv()`가 정지되는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿