У меня есть чат-сервер, на котором работает несколько клиентов, и он прекрасно работает, когда одно сообщение отправляется одним клиентом, а затем другим клиентом вводит его в качестве входа для получения сообщения с сервера. Однако, когда один клиент отправляет два сообщения, а другой пытается их получить, я получаю неверную буквальную ошибку, из-за которой соединение закрывается. Я не знаю, что происходит, и я не понимаю, как это исправить. Пожалуйста помоги! Любые предложения приветствуются!
Сервер:
import socket
import select
host = '127.0.0.1'
port = 65432
HEADER_LENGTH = 100
def socket_setup():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Creating socket object
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Allowing the same address to be reused
s.bind((host, port)) # Binding the socket to the IP address and port number
s.listen() # Listening for incoming connections
print(f'Listening for incoming connections on IP address {host}.')
return s
def client_data(s):
client_socket_list = [s] # List for appending connected sockets to for select to keep track of
clients = {} # Dict for informing other clients in a better way than just socket info who they are
return client_socket_list, clients
def receiving_messages(client_socket):
try:
msg_header = client_socket.recv(HEADER_LENGTH) # Getting the message header
# If we do not get any data for the message header then we need code to handle this
if not len(msg_header):
return False
else:
msg_length = int(msg_header.decode("utf-8")) # Converting the header to a length
return {"header": msg_header, "data": client_socket.recv(msg_length)} # Returning the data from the message
except:
return False
def client_accept(s):
client_socket, client_address = s.accept() # Accepting a new connection, getting unique client socket and address
user = receiving_messages(client_socket) # User data
return client_socket, client_address, user
def info_update(client_socket, client_socket_list, clients, user, client_address):
client_socket_list.append(client_socket) # Adding the new client socket to the list
clients[client_socket] = user # Adding the user information to the clients dictionary
print(f"New connection accepted from IP: {client_address[0]} Port: {client_address[1]} username:
{user['data'].decode('utf-8')}")
return clients
def broadcast(clients, x, user, message): # Now sharing the message with all other users in the chatroom
for client_socket in clients: # Iterating over all connected clients
if client_socket != x: # Stopping the message being sent out to the client that sent the message
client_socket.send(user['header'] + user['data'] + message['header'] + message['data']) # Sending the message from client X to all other clients
def message_handling(client_socket_list, s, clients):
while True:
# Below socket is taking in parameters (1, 2, 3) (1) the read list(things we want to read in)(2) the sockets we want to write (3) sockets with possible error
read_sockets, _, exception_sockets = select.select(client_socket_list, [], client_socket_list)
for x in read_sockets: # x = socket that has been notified of chat room entry (iterating over sockets with info to be read). Iterating over all sockets in the list.
if x == s: # Handling for a new connection
client_socket, clients_address, user = client_accept(s)
if user is False: # Handling for a disconnection
continue
info_update(client_socket, client_socket_list, clients, user, clients_address)
else:
message = receiving_messages(x) # If the socket is not the server socket then we have a message to read
if message is False:
print(f"Connection closed from {clients[x]['data'].decode('utf-8')}")
client_socket_list.remove(x) # Removing the socket on which the connection has been closed from the list of clients
del clients[x] # Removing the client info from the dict
continue
user = clients[x]
print(f"Received message from {user['data'].decode('utf-8')}:
{message['data'].decode('utf-8')}")
broadcast(clients, x, user, message)
# Removing users if there is a socket error causing unexpected connection closure
for x in exception_sockets:
client_socket_list.remove(x)
del clients[x]
def main():
s = socket_setup()
client_socket_list, clients = client_data(s)
message_handling(client_socket_list, s, clients)
if __name__ == "__main__":
main()
Клиент:
import socket
import errno
import sys
HEADER_LENGTH = 100
host = '127.0.0.1'
port = 65432
def client_socket_setup():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host, port))
client_socket.setblocking(False) # Telling the recv method not to block
return client_socket
def username(client_socket): # Server expects the first message to be a username input by the user
my_username = input('Username: ') # User input of username (Not encoded in utf-8 bytes)
username = my_username.encode('utf-8') # Encoding the user into bytes to send
username_header = f'{len(username):<{HEADER_LENGTH}}'.encode('utf-8') # Defining a variable username_header and stating that the length of the username must be aligned to the left within the specified length set by HEADER_LENGTH
client_socket.send(username_header + username) # Sending client username info to the server
return my_username, username_header
def message_sending(message, HEADER_LENGTH, client_socket):
message = message.encode('utf-8') # Encoding the message into utf-8 bytes ready to send to the
server
message_header = f'{len(message):<{HEADER_LENGTH}}'.encode('utf-8') # Defining a variable message_header containing the information that the length of the message must be aligned to the left within the length of the username header
client_socket.send(message_header + message) # Encoded message now sent along with the message length info
def receiving_user(username_header, client_socket): # Getting the username of the other client that sent the last message
username_length = int(username_header.decode('utf-8'))
username = client_socket.recv(username_length).decode('utf-8')
return username
def receiving_message(client_socket): # Getting the message from the server that the other client has sent
message_header = client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode('utf-8').strip())
username_length = message_length + 1 # Fix for the bug that was causing the invalid literal parsing error!
message = client_socket.recv(username_length).decode('utf-8')
return message
def send_and_recv(my_username, client_socket, HEADER_LENGTH):
while True:
message = input(f'{my_username} : ') # my_username used so it is not already encoded when using it here to attach the message the user inputs
# Sending messages and handling for an empty input i.e. no message input
if message:
message_sending(message, HEADER_LENGTH, client_socket)
try:
while True:
# Receiving messages from other clients
username_header = client_socket.recv(HEADER_LENGTH)
if not len(username_header): # Handling for an error where the username header length is not what it should be
print('connection closed by the server')
sys.exit() # System closing the connection due to no more messages
username = receiving_user(username_header, client_socket)
message = receiving_message(client_socket)
print(f'{username}: {message}') # Printing the message from the other client along with that clients username
# Preventing consistent errors being raised causing issue within the program as within a non-blocking connection an error will continually be raised when no messages are coming through etc
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print('Expecting message but not receiving ', str(e))
sys.exit()
continue
# Handling for all other unexpected errors that may occur
except Exception as e:
print('General error: ', str(e))
sys.exit()
def main():
client_socket = client_socket_setup()
my_username, username_header = username(client_socket)
send_and_recv(my_username, client_socket, HEADER_LENGTH)
if __name__ == "__main__":
main()
Ошибка:
File "C:/Users/hassallj/Documents/Python Scripts/Chat_Server_and_Client/Chat_App/Client.py", line 60, in send_and_recv username = receiving_user(username_header, client_socket) File "C:/Users/hassallj/Documents/Python Scripts/Chat_Server_and_Client/Chat_App/Client.py", line 31, in receiving_user username_length = int(username_header.decode('utf-8')) ValueError: invalid literal for int() with base 10: '