I'm trying to learn the use of sockets in python by writing a simple chat program with one server and multiple clients connected. Everything works relatively well when I only have one client connected, but if I connect a second client, the first one continues to receive messages, but can no longer send them.
This is the server:
from pickle import TRUE
import socket
import threaded
from threading import Thread
import _thread
import os
import time
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
ip = str(local_ip)
port = 55555
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, port))
server.listen()
global clients
clients = []
def recive(client):
global clients
name = client.recv(2024)
name = name.decode("utf-8")
while True:
try:
string = client.recv(2024)
string = string.decode("utf-8")
if string == "!exit":
client.close()
print("Connection interrupted")
break
else:
for client in clients:
client.send(bytes(string, "utf-8"))
print(f"{name}: {string}")
except:
client.close()
print("Connection interrupted")
break
if __name__ == "__main__":
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
ip = str(local_ip)
port = 55555
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, port))
server.listen()
print(f"Server listening on {ip} on port {port}")
while True:
client, address = server.accept()
print(f"Connectione estabished - {address[0]}:{address[1]}")
clients.append(client)
_thread.start_new_thread(recive ,(client,))
This is the client:
from email import message
import socket
from xml.etree.ElementTree import tostring
import threaded
from threading import Thread
import _thread
import os
import time
global string
global text
string = "string"
text = "text"
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
ip = str(local_ip)
port = 55555
name = str(input("Insert your name: "))
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect((ip, port))
def recive(server):
global string
global text
while True:
text = server.recv(2024)
text = text.decode('utf-8')
if text == string:
pass
else:
print(f"Broadcasted: {text}")
def send(server):
global string
global text
server.send(bytes(name, "utf-8"))
while True:
string = str(input("Enter string: "))
if string == "!exit":
server.send(bytes(string, "utf-8"))
server.close()
break
else:
server.send(bytes(string, "utf-8"))
_thread.start_new_thread(recive ,(server,))
send(server)
If other information is needed, I will take care to modify the request and insert them.
Since English is not my first language, I apologize for any mistakes.
CodePudding user response:
In the function def recive(client): ...
, the variable client
holds the socket for a communication with one specific client. But in this loop:
for client in clients:
client.send(bytes(string, "utf-8"))
print(f"{name}: {string}")
the client
variable gets overwritten and after the loop, the function communicates with a wrong socket, i.e. wrong client. Just use a separate variable:
for c in clients:
c.send(bytes(string, "utf-8"))
P.S. To prevent the Address already in use
error when restarting the server, add immediately before the line server.bind(...)
:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)