Python socket - получение с сервера не работает - PullRequest
0 голосов
/ 15 февраля 2019

У меня проблема с клиентом и сервером Python socket - мне нужен следующий обмен:

  • Клиент отправляет сообщение на сервер.
  • Сервер читает сообщение и делаетоснованное на нем решение.
  • Сервер отправляет соответствующее сообщение клиенту.

Я застреваю в последнем пункте.Что бы я ни пытался, клиент не получит сообщение, отправленное сервером.Обратитесь к приведенному ниже коду:

Клиент:

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'Send to server '] от клиента

Что не работает, так как клиент ничего не получил.

Если вы раскомментируете строку

self.conn.sendall(b"Send to client")

в Server.recv_info (), то внезапно это сработает.Но мне нужно держать sendall вне цикла while True, я думаю, если входящее сообщение разделено на несколько пакетов?Я не уверен, почему это будет работать, когда sendall вне цикла не работает.

Я думаю, что в сокетах должно быть что-то, чего я не понимаю.Я поиграл с блокировкой / неблокировкой, закрытием соединения с сокетом, добавлением времени ожидания и прочел много вопросов здесь (самый близкий, что я нашел, это У меня проблемы с тем, чтобы заставить сервер сокетов Python получать командыиз клиента сокета Python ), но безрезультатно.Любые идеи будут приветствоваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...