我在使用Python套接字客户端和服务器时遇到问题-我想要进行以下交换:
我被困在最后一点。不管我尝试什么,客户端都不会收到服务器发送的消息。请参阅下面的代码:
客户:
import socket, select
ip = ["10.189.165.14", 25565]
# Client class to manage server connections
class Client:
def __init__(self, ip:list):
self.sock = socket.socket() # Create the socket object
ip[1] = int(ip[1]) # Convert the port number provided into an int
self.ip = tuple(ip) # Save the inputted IP and port (sock.connect requires a tuple, so convert it here)
def connect(self):
"""Method to attempt to connect to the server"""
self.sock.settimeout(3) # Set the timeout period that the client will try to connect for
self.sock.connect(self.ip) # Connection to the host and port
self.conn = self.sock # Set self.conn = self.sock, for consistent variable naming with the server code
self.sock.setblocking(False) # Set socket to be non-blocking so it errors with BlockingIOError instead of blocking the connection
print("This is the CLIENT; Connected to server")
return True # Return True to the caller so it knows a successful connection has been established
def recv_info(self):
"""Method to receive information from the server in an x byte string"""
for _ in range(100): # Run this method multiple times, until the incoming variable receives information
incoming, _, _ = select.select([self.conn], [], [], 0.01) # Monitor incoming messages from the socket
if incoming: # If there is an incoming message from the server
dataRecv = []
while True: # Infinite loop to break the received bytes data into chunks and load them individually
packet = b"" # Reset packet to a blank byte string
try:
packet = self.conn.recv(4096) # Receive data from server into packet
except BlockingIOError: # If packet gets nothing from the recv()
break # Break out of this while loop
if not packet:
break # If the packet has received nothing from the connection, break this loop
dataRecv.append(packet) # Add the packet onto dataRecv
return dataRecv # Return the received message
client = Client(ip) # Create the client object
conn = client.connect() # Establish a connection with the server
if conn == True: # If connection is successful
client.conn.sendall(b"Send to server") # Send message to the server
print("Sent to server")
recv = client.recv_info() # Look for message from the server
print(f"Received {recv} from server")
服务器:
import socket, select
class Server:
def __init__(self):
self.sock = socket.socket() # Create the socket object upon instantiation
self.ip = (socket.gethostbyname(socket.gethostname()), 25565) # Make machine name, socket and port visible to the outside world
self.sock.bind(self.ip) # Bind the IP and port to the socket
def connect(self):
"""Method to connect to a client socket"""
self.sock.settimeout(5) # Set the timeout period that the server will wait for a connection
self.sock.listen(5) # Number of allowed unaccepted connections before refusing new connections (i.e. connection queue length)
try:
self.conn, addr = self.sock.accept() # Wait to establish connection with an outside client
except socket.timeout: # If the timeout period elapses without a connection
return False # Exit this method
print("This is the SERVER; Connected to client")
self.sock.setblocking(False) # Set socket to be non-blocking so it errors with BlockingIOError instead of blocking the connection
return True # Return True so the caller knows that a connection has been established
def recv_info(self):
"""Method to receive information from the client in an x byte string"""
for _ in range(100): # Run this method multiple times, until the incoming variable receives information
incoming, _, _ = select.select([self.conn], [], [], 0.01) # Monitor incoming messages from the socket
if incoming: # If there is an incoming message from the client
dataRecv = [] # Start dataRecv as an empty list for this _ iteration
while True: # Infinite loop while receiving data
packet = b"" # Reset packet to a blank byte string
try:
packet = self.conn.recv(4096) # Receive data from client into packet
except BlockingIOError: # If self.conn.recv() is blocked
break # Break out of this while loop
if not packet: # If packet gets nothing from the recv()
break # Break out of this while loop
dataRecv.append(packet) # Add the packet onto dataRecv
# self.conn.sendall(b"Send to client")
print(f"Received {dataRecv} from client")
# Decision making logic to decide on what msg should be
msg = b"Send to client"
self.conn.sendall(msg)
print("Sent to client")
break # Break out of the outer incoming attempts loop
server = Server() # Initialise the server
serverRunning = True
while serverRunning == True: # This boolean always starts as True
conn = server.connect() # Check for a client connection; will return True or False
if conn == True:
# When a connection is established, receive information from the client
server.recv_info() # recv_info() contains an infinite loop to receive information
运行此命令可获得输出:
客户:
这是客户端;已连接到服务器
已发送到服务器
没有收到来自服务器的消息
服务器:
这是服务器;已连接到客户端
发送给客户
从客户端收到[b'发送到服务器']
哪个没有工作,因为客户端什么都没收到。
如果您取消注释该行
self.conn.sendall(b"Send to client")
在Server.recv_info()中,然后突然生效。但是我认为,如果传入消息被拆分为多个数据包,我想将sendall保留在while True循环之外?我不确定为什么在循环外的sendall无效时为什么会起作用。
我认为这里一定有我不了解的套接字。我一直在尝试阻塞/不阻塞,关闭套接字连接,添加等待时间,并在此处阅读了很多问题(我发现最近的问题是I got problems with making a Python socket server receive commands from a Python socket client),但无济于事。任何想法都将受到欢迎。