I wrote p2p chat. The essence of the code is as follows:
The server works without errors as it seems to me, and when the client starts, the following File
"d:\\p2p_chat.py", line 60, in start_listen listener.bind((host, port))
OSError: [WinError 10048] Usually only one use of the socket address (protocol/network address/port) is allowed What is the error and are there any other flaws in the code.
Thanks in advance
#server.py
import socket
TCP_MAX_SIZE=65535
def listen(host: str='127.0.0.1', port: int=9000 ):
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(0)
print(f'Listening at {host}:{port}')
members=[]
while True:
conn, addr = s.accept()
msg=conn.recv(TCP_MAX_SIZE)
if addr not in members:
members.append(addr)
if not msg:
continue
client_id=addr[1]
msg_text=msg.decode('utf-8')
if msg_text=='__join':
print(f'Client {client_id} joined chat')
continue
message_template='{}__{}'
if msg_text=='__members':
print(f'Client {client_id} requsted members')
active_members=[f'client{m[1]}'for m in members if m!=addr]
members_msg=';'.join(active_members)
conn.send(message_template.format('members',members_msg).encode('utf-8'))
if __name__=='__main__':
listen()
#client.py
import socket
import os
import random
TCP_MAX_SIZE = 4096
COMMANDS = ['/members', '/exit', '/connect', '/help', '/send']
HELP_TEXT = '''
/members - list members in chat
/connect clientX - connect to clientX
/exit - exit chat
/send path_to_file - send a file
'''
def start_listen(s, host, port):
def listen():
while True:
try:
conn, addr = s.accept()
except OSError:
continue
print(f'Connected by {addr}')
peer_port = addr[1]
if peer_port not in listen.allowed_ports:
conn.close()
continue
while True:
data = conn.recv(TCP_MAX_SIZE)
if not data:
print(f'Disconnect from {addr}')
break
print(f'client{peer_port}: {data.decode("utf-8")}')
if data.startswith('__join'):
conn.send('__joined'.encode('utf-8'))
elif data.startswith('__members'):
members = [f'client{p}' for p in listen.allowed_ports if p != peer_port]
conn.send(('\n'.join(members)).encode('utf-8'))
elif data.startswith('__exit'):
print(f'Disconnect from {addr}')
conn.close()
break
elif data.startswith('file__'):
filename, filesize = data.decode('utf-8').split('__')
filesize = int(filesize)
with open(filename, 'wb') as f:
bytes_received = 0
while bytes_received < filesize:
chunk = conn.recv(TCP_MAX_SIZE)
f.write(chunk)
bytes_received += len(chunk)
print(f'Successfully received file {filename}, size {filesize} bytes')
else:
print(f'client{peer_port}: {data.decode("utf-8")}')
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.bind((host, port))
listener.listen()
listener.allowed_ports = []
return listener.listen()
def connect(host='127.0.0.1', port=9000):
addsr = host, port
own_port = random.randint(8000, 9000)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, own_port))
listen_thread = start_listen(s, host, port)
allowed_ports = [port]
listen_thread.allowed_ports = allowed_ports
try:
s.connect((host, port))
s.send('__join'.encode('utf-8'))
except OSError as e:
print(f"Error: {e}")
while True:
msg = input(f'you: ')
command = msg.split(' ')[0]
if command in COMMANDS:
if msg == '/members':
s.send('__members'.encode('utf-8'), len(addsr))
if msg == '/exit':
peer_port = s.getpeername()[1]
allowed_ports.remove(peer_port)
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, own_port))
listen_thread = start_listen(s, host, port)
listen_thread.allowed_ports = allowed_ports
s.connect((host, port))
s.send('__exit'.encode('utf-8'))
print(f'Disconnect from client{peer_port}')
if msg.startswith('/connect'):
peer = msg.split(' ')[-1]
peer_port = int(peer.replace('client', ''))
allowed_ports.append(peer_port)
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, own_port))
listen_thread = start_listen(s, host, port)
listen_thread.allowed_ports = allowed_ports
s.connect((host, port))
s.send('__join'.encode('utf-8'))
print(f'Connected to client{peer_port}')
if msg == '/help':
print(HELP_TEXT)
if msg.startswith('/send'):
filepath = msg.split(' ')[-1]
filename = os.path.basename(filepath)
filesize = os.path.getsize(filepath)
s.send(f'file__{filename}__{filesize}'.encode('utf-8'))
with open(filepath, 'rb') as f:
bytes_sent = 0
while bytes_sent < filesize:
data = f.read(TCP_MAX_SIZE)
s.send(data)
bytes_sent += len(data)
print(f'Successfully sent file {filename}, size {filesize} bytes')
else:
s.send(msg.encode('utf-8'))
if __name__ == '__main__':
connect()
Your error say you the answer.
If you call the method start_listen
in your client.py
you need to change the listen port. Your server.py
is already listen to port 9000 on localhost.
And your `client.py' also want to listen on the same port wich is not possible.
Another hint: Close the socket after listen.