i am trying to get message from a client using threads.I need to send the message to all the connected client threads my server code is
import socket
import threading
class seversocket:
def __init__(self):
self.header=64
self.port=5055
self.format='utf-8'
self.hostname=socket.gethostname()
self.host=socket.gethostbyname(self.hostname)
self.close='close'
self.messagelist=['world']
self.addr=(self.host,self.port)
self.soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.soc.bind(self.addr)
print('server socket created and binded;')
self.listener()
def messageupdate(self,msgcount):
result_list=[]
if(len(self.messagelist)>msgcount):
result_list=self.messagelist[msgcount:]
return result_list,len(self.messagelist)
else:
return None,msgcount
def clients(self,conn,addr):
print(f'connected to {addr}')
connected=True
msgcount=0
while connected:
msglen=conn.recv(self.header).decode(self.format)
if msglen:
msglen=int(msglen)
msg = conn.recv(msglen).decode(self.format)
if msg == self.close:
connected=False
print(f"[{addr}]{msg}")
li,msgcount= self.messageupdate(msgcount)
if li is not None:
for i in li:
print(i)
message=i.encode(self.format)
print(message)
msglen=len(message)
print(msglen)
sendlen=str(msglen).encode(self.format)
sendlen += b' '*(self.header-len(sendlen))
conn.send(sendlen)
conn.send(message)
conn.close()
def listener(self):
self.soc.listen()
print(f'socket is listening to {self.host}')
while True:
conn,addr=self.soc.accept()
thread=threading.Thread(target=self.clients,args=(conn,addr))
thread.start()
def listappened(self,mes):
self.messagelist.append(mes)
return None
seversocket()
my clientscript is
import socket
import threading
class clientsocket:
def __init__(self):
self.header=64
self.port=5055
self.format='utf-8'
self.hostname=socket.gethostname()
self.host=socket.gethostbyname(self.hostname)
self.close='close'
self.addr=(self.host,self.port)
self.client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.client.connect(self.addr)
self.check=threading.Thread(target=self.checkformessgae)
def send(self,msg):
message=msg.encode(self.format)
msglen=len(message)
sendlen=str(msglen).encode(self.format)
sendlen += b' '*(self.header-len(sendlen))
self.client.send(sendlen)
self.client.send(message)
def checkformessgae(self):
msglen=self.client.recv(self.header).decode(self.format)
if msglen:
msglen=int(msglen)
msg =self.client.recv(msglen).decode(self.format)
if msg == self.close:
connected=False
print(f"[{addr}]{msg}")
k=clientsocket()
k.send('hello')
when i run the server the server is running,but when i run the clientscript server script throws the following error
when i debug the code line by line the error i occuring in the serverscript when i try to send the message conn.send(sendlen) conn.send(message)
So, a minimal example of your situation would be:
import socket, time
import threading
header = 64
soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('', 5055))
soc.listen()
conn, addr = soc.accept()
def loop(conn):
while True:
msglen = conn.recv(header).decode('UTF-8')
if msglen:
msglen = int(msglen)
msg = conn.recv(msglen).decode('UTF-8')
print(msg)
conn.send(b'10')
conn.send(b'0123456789')
time.sleep(0.025)
thread = threading.Thread(target=loop, args=(conn,))
thread.start()
Now, because threading has nothing to do with this, I can also reduce the code to the actual problem which is the socket part.
(This might come from experience, it might also just come from searching the issue online and you'll find plenty of resources covering "connection reset by peer") .
So, if we reduce it to the core components of the issue, it looks like this:
import socket
# No threading needed to reproduce the problem
header = 64
soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('', 5055))
soc.listen()
conn, addr = soc.accept()
while True: # Replaced thread with a simple while loop
msglen = conn.recv(header).decode('UTF-8')
if msglen:
msglen = int(msglen)
msg = conn.recv(msglen).decode('UTF-8')
print(msg)
conn.send(b'10')
conn.send(b'0123456789')
Which gives me:
PS C:\Users\anton> python .\server.py
hello
Traceback (most recent call last):
File ".\server.py", line 12, in <module>
msglen = conn.recv(header).decode('UTF-8')
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
Now, my error message is slightly different. And that is because I'm on windows and you're on Linux. But the jizt is the same, "Connection reset" by some party of the connection.
Now, why is this?
Quite simple, it's because the other end of the connection (client in this case, since the problem is on the server end of things) closed the connection. And why is that? Well it's because there's nothing keeping the client alive. All it does is send hello
, check if there's any incoming data and do print(f"[{addr}]{msg}")
. After that, the client quits.
So while that happens, you're trying to do (multiple times) :
conn.recv(msglen)
Which won't work because there's nothing on the other end.
So the solution to your problem is, don't quit the client. And also, do error handling. There's a lot to cover in this topic as server and client side software has a lot of pitfalls. But in your case, doing:
try:
ConnectionResetError
except ConnectionResetError:
self.close()
Or you could switch to a more fault-friendly way of first checking if there's data via the select library.
import socket, select
header = 64
soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('', 5055))
soc.listen()
conn, addr = soc.accept()
while True:
readable, writable, exceptional = select.select([conn], [conn], [])
print(readable)
if readable:
msglen = conn.recv(header).decode('UTF-8')
if msglen:
msglen = int(msglen)
msg = conn.recv(msglen).decode('UTF-8')
print(msg)
# Could technically check writable here, just to be sure
print(writable)
conn.send(b'10')
conn.send(b'0123456789')
But even then, that might fail because of timing issue between checking and trying to read. That's where epoll comes in, it can trigger on events and be a bit more flexible (maybe you can achieve the same with select.select
but I gave up a long time ago so don't know myself) .
import socket, select
header = 64
soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('', 5055))
soc.listen()
conn, addr = soc.accept()
poll_obj = select.epoll()
poll_obj.register(conn.fileno(), select.EPOLLIN | select.EPOLLHUP)
while True:
for fileno, eventid in poll_obj.poll(0.5):
if eventid == select.EPOLLIN:
msglen = conn.recv(header).decode('UTF-8')
if msglen:
msglen = int(msglen)
msg = conn.recv(msglen).decode('UTF-8')
print(msg)
conn.send(b'10')
conn.send(b'0123456789')
else:
print('Client disconnected (prob eventid 25)')
break
This will firstly verify that there's data on the pipe, then it will determinate if the data is actual data or if it's a underlying socket event ( RST/ACK
for instance was sent). If all is OK, you (should) can probably receive data without errors. As long as you handle the disconnects.
Bake this into your thread logic again, and you should be good to go.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.