简体   繁体   中英

python TCP communication threaded, delay and error

I would like to ask you a question about a trouble i found while i was coding to improve my skill in TCP communication. Basically i first learn about socket and how to open server/client socket and communication. So i wrote one class for server and one for client, i test it and i found they work very fine for what i care: this is the server

class server_class:
    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock
    def bind(self,host, port):
        self.sock.bind((host, port))
    def listen(self,client):
        self.sock.listen(client)
    def close_client(self):
        self.client.close()
    def accept(self):
        self.client,self.c_addr=self.sock.accept()
    def invia(self,MSGLEN,msg):
        totalsent = 0
        if(len(msg)<MSGLEN):
            while(len(msg)<MSGLEN):
                msg=msg+'*'
        while totalsent < MSGLEN:
            sent = self.client.send(msg[totalsent:].encode('ascii'))
            if sent == 0:
                raise RuntimeError
            totalsent = totalsent + sent
    def ricevi(self,MSGLEN):
        msg = ''
        while len(msg) < MSGLEN:
            chunk = self.client.recv(MSGLEN-len(msg)).decode('ascii')
            if chunk == '':
                raise RuntimeError
            msg = msg + chunk
        i=0
        messaggio=''
        while(i<MSGLEN):
            if(msg[i]!='*'):
                    mess=msg[i]
                    messaggio=messaggio+mess

            else:
                    pass
            i+=1
        return messaggio

and this is the client:

class client_class:
    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock
    def connect(self,host,port):
        self.sock.connect((host, port))

    def invia(self,MSGLEN,msg):
        totalsent = 0
        if(len(msg)<MSGLEN):
            while(len(msg)<MSGLEN):
                msg=msg+'*'
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:].encode('ascii'))
            if sent == 0:
                raise RuntimeError
            totalsent = totalsent + sent
    def ricevi(self,MSGLEN):
        msg = ''
        while len(msg) < MSGLEN:
            chunk = self.sock.recv(MSGLEN-len(msg)).decode('ascii')
            if chunk == '':
                raise RuntimeError
            msg = msg + chunk
        i=0
        messaggio=''
        while(i<MSGLEN):
            if(msg[i]!='*'):
                    mess=msg[i]
            else:
                    pass
            messaggio=messaggio+mess
            i+=1
        return messaggio

So no at all problem at this time. Next step i tried to do was to write a program that while doing some math or GUI or both, keep a server on for communicate to a client the information it work out in math for example. The only way i found to do this is use threading module. I write 2 function, one for server and one for math (increase x value in while loop) and add in main a GUI. Then i pass each function to a thread. This is the server function (that use server class defined before):

def server():

global Stop,x
server=server_class()
ip='192.168.1.134'
port=8033
server.bind(ip,port)
Stop=True
client=0
c_addr=0

while(Stop):
    server.listen(1)
    print("* inizio ascolto su",ip,":",port)
    server.accept()
    print("* mi sono connesso con",server.c_addr[0],":",server.c_addr[1])
    while(Stop):
            data=server.ricevi(100)
            print(data)

            if(data=="disconnetti"):
                msg="bye bye"
                server.invia(100,msg)
                server.close_client()
                print("*disconnetto il client")
                break

            if(data=="inviami x"):
                 msg=str(x)
                 server.invia(100,msg)

            if(data=="chiudi server"):
                print("*chiudo server")
                server.close_client()
                Stop=False
            else:
                 msg="come?"
                 server.invia(100,msg)

This is the math function named 'go':

def go():
global x
while(x<10000):
    x+=1
    time.sleep(1)

Finally the main function is:

finestra=Tk()
finestra.geometry('800x800+300+300')
finestra.title('Prova threading')
testo_0=Label(finestra,text="Valore attuale:").grid(sticky=W,row=0,column=0)
gobutton=Button(finestra,text='Acquisisci',command=lambda: leggi())
gobutton.grid(row=2, column=1)

goo=threading.Thread(target=go)
serv=threading.Thread(target=server)
goo.start()
serv.start()
finestra.mainloop()

So go function increase continuously x value, server function keep a server listening and main thread keep a GUI within which a user can see x value by pressing a botton. The server knows just 3 commands from client: 1)pass x to client 2)close client 3)close server for other message it answer as unknown command. What happen is that the communication doesn't work good; for example when from a client (running on other machine using the client class defined before) ask to server to pass x value (that go function is constantly increasing) happen 2 wrong things: 1) After the first communication other seems delayed, for example the second time i ask x value the server answer as unknown command, third time i send a request for x value it give me a value. Next time its going to answer as unknown and next give me a value and so on. 2) After the first communication too, the values that server pass to client are delayed, so for example if at the same time i send to server request for x and push the botton in GUI for read x value, these are going to be appreciably different.

This is the client script i use:

import time
import socket


class client_class:
    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock
    def connect(self,host,port):
        self.sock.connect((host, port))

    def invia(self,MSGLEN,msg):
        totalsent = 0
        if(len(msg)<MSGLEN):
            while(len(msg)<MSGLEN):
                msg=msg+'*'
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:].encode('ascii'))
            if sent == 0:
                raise RuntimeError
            totalsent = totalsent + sent
    def ricevi(self,MSGLEN):
        msg = ''
        while len(msg) < MSGLEN:
            chunk = self.sock.recv(MSGLEN-len(msg)).decode('ascii')
            if chunk == '':
                raise RuntimeError
            msg = msg + chunk
        i=0
        messaggio=''
        while(i<MSGLEN):
            if(msg[i]!='*'):
                    mess=msg[i]
            else:
                    pass
            messaggio=messaggio+mess
            i+=1
        return messaggio


client=mysocket()
ip='192.168.1.134'
port=8033
client.connect(ip,port)


while(True):
    print("inserire comando da inviare (max 100 Bytes)")
    msg=input().encode('ascii')
    client.invia(100,msg)
    print(client.ricevi(100).decode('ascii'))

Any help will be appreciate, thank you very much and sorry for bad english

UPDATE

I found that if i close socket on each communication, so for example everytime i need to send a message i open a client socket and close it after send it, could solve the problem, no error and no delay. Can't explain me why, so if anyone could answer it will be appreciated. Thank you very much

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