【发布时间】:2017-05-22 07:13:05
【问题描述】:
我想问你一个问题,关于我在编码时发现的一个问题,以提高我在 TCP 通信方面的技能。基本上我首先了解套接字以及如何打开服务器/客户端套接字和通信。所以我为服务器编写了一个类,为客户端编写了一个类,我对其进行了测试,我发现它们对我所关心的工作非常好:这是服务器
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
这是客户:
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
所以目前完全没有问题。我尝试做的下一步是编写一个程序,在做一些数学或 GUI 或两者时,保持服务器开启,以便与客户端通信它在数学中计算出的信息。我发现这样做的唯一方法是使用线程模块。 我编写了 2 个函数,一个用于服务器,一个用于数学(在 while 循环中增加 x 值)并在 main 中添加一个 GUI。然后我将每个函数传递给一个线程。 这是服务器函数(使用之前定义的服务器类):
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)
这是名为“go”的数学函数:
def go():
global x
while(x<10000):
x+=1
time.sleep(1)
最后主要的功能是:
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()
所以 go 函数不断增加 x 值,服务器函数保持服务器监听,主线程保持一个 GUI,用户可以通过按下按钮在其中看到 x 值。 服务器只知道来自客户端的 3 个命令: 1) 将 x 传递给客户端 2)关闭客户端 3)关闭服务器 对于其他消息,它以未知命令回答。 发生的情况是沟通不好;例如,当来自客户端(使用之前定义的客户端类在其他机器上运行)要求服务器传递 x 值(该 go 函数不断增加)时,会发生 2 件错误的事情: 1)在第一次通信之后,其他似乎延迟了,例如第二次我问 x 值服务器回答为未知命令,第三次我发送一个 x 值请求它给了我一个值。下次它会回答为未知,然后给我一个值等等。 2)在第一次通信之后,服务器传递给客户端的值也会延迟,所以例如,如果同时我向服务器发送 x 请求并在 GUI 中按下按钮以读取 x 值,这些将是明显的不同。
这是我使用的客户端脚本:
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'))
任何帮助将不胜感激,非常感谢您,对英语不好表示抱歉
【问题讨论】:
标签: python multithreading sockets tcp