我知道这篇文章有点老,但我希望能对某些人有所帮助。
使用普通的Python套接字,我发现你可以使用sendto和recvfrom以数据包的形式发送和接收信息。
import socket
ADDRESS = ''
PORT = 54321
connections = []
host = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host.setblocking(0)
host.bind((ADDRESS, PORT))
host.listen(10)
def close_socket(connection):
try:
connection.shutdown(socket.SHUT_RDWR)
except:
pass
try:
connection.close()
except:
pass
def read():
for i in reversed(range(len(connections))):
try:
data, sender = connections[i][0].recvfrom(1500)
return data
except (BlockingIOError, socket.timeout, OSError):
pass
except (ConnectionResetError, ConnectionAbortedError):
close_socket(connections[i][0])
connections.pop(i)
return b''
def write(data):
for i in reversed(range(len(connections))):
try:
connections[i][0].sendto(data, connections[i][1])
except (BlockingIOError, socket.timeout, OSError):
pass
except (ConnectionResetError, ConnectionAbortedError):
close_socket(connections[i][0])
connections.pop(i)
while True:
try:
con, addr = host.accept()
connections.append((con, addr))
except BlockingIOError:
pass
data = read()
if data != b'':
print(data)
write(b'ECHO: ' + data)
if data == b"exit":
break
for i in reversed(range(len(connections))):
close_socket(connections[i][0])
connections.pop(i)
close_socket(host)
客户端类似
import socket
ADDRESS = "localhost"
PORT = 54321
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ADDRESS, PORT))
s.setblocking(0)
def close_socket(connection):
try:
connection.shutdown(socket.SHUT_RDWR)
except:
pass
try:
connection.close()
except:
pass
def read():
"""Read data and return the read bytes."""
try:
data, sender = s.recvfrom(1500)
return data
except (BlockingIOError, socket.timeout, AttributeError, OSError):
return b''
except (ConnectionResetError, ConnectionAbortedError, AttributeError):
close_socket(s)
return b''
def write(data):
try:
s.sendto(data, (ADDRESS, PORT))
except (ConnectionResetError, ConnectionAbortedError):
close_socket(s)
while True:
msg = input("Enter a message: ")
write(msg.encode('utf-8'))
data = read()
if data != b"":
print("Message Received:", data)
if msg == "exit":
break
close_socket(s)
:
的形式发送。接收时,检测到:
后就一直用recv
接收直到获取消息的长度,然后根据头部明确地使用recv
获取需要的内容。如果是文件,则循环接收文件的块,同时确保recv
的大小可被2整除,直到最后一个字节(如果总字节数 % 2 != 0
)。我使用这种方法传输大文件(几个GB),这对于显示进度条也很有帮助。 - RattleyCooperrecv(bufsize)
,它发送了较少的数据。但我的问题是 Python 如何理解这是结束?由于 TCP 是一个流,服务器如何检测流中的数据结束? - peiman F.