简体   繁体   中英

server script is not sending message in python sockets

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM