Python套接字-从服务器接收无法正常工作

时间:2019-02-14 21:45:32

标签: python sockets

我在使用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),但无济于事。任何想法都将受到欢迎。

0 个答案:

没有答案