客户端需要同时发送和接收数据,但当没有数据从服务器接收时,客户端会挂起,导致无法发送数据。
- 解决方案:
使用多线程实现数据的收发并行处理。
from socket import *
from threading import *
import thread
import time
from struct import pack,unpack
from networklingo import *
#from exception import *
HOST = '192.168.0.105'
PORT = 21567
BUFFSIZE = 1024
ADDR = (HOST,PORT)
lock = thread.allocate_lock()
class TronClient:
def __init__(self,control=None):
self.tcpSock = socket(AF_INET,SOCK_STREAM)
#self.tcpSock.settimeout(.2)
self.recvBuff = []
def connect(self):
self.tcpSock.connect(ADDR)
self.clientUID = self.tcpSock.recv(BUFFSIZE)
print 'My clientUID is ', self.clientUID
t = Thread(target = self.receiveFromSrv())
t.setDaemon(1)
t.start()
print 'going to main loop'
self.mainLoop()
def receiveFromSrv(self):
RECIEVING = 1
while RECIEVING:
# 非阻塞模式下,当没有数据时不会阻塞
self.tcpSock.setblocking(0)
try:
data = self.tcpSock.recv(BUFFSIZE)
# 当数据为空时,继续等待
except socket.error as e:
if e.errno == EINTR:
continue
else:
print('Error recieving data, ',e)
continue
# 收到数据后,进行处理
if not data: continue
header = data[:6]
msgType,msgLength,clientID = unpack("hhh",header)
print(msgType)
print(msgLength)
print(clientID,'\n')
msg = data[6:]
while len(msg) < msgLength:
data = self.tcpSock.recv(BUFFSIZE)
dataLen = len(data)
if dataLen <= msgLength:
msg += data
else:
remLen = msgLength-len(data) #we just need to retrieve first bit of data to complete msg
msg += data[:remLen]
self.recvBuff.append(data[remLen:])
print(msg)
def disconnect(self,data=''):
self.send(DISCONNECT_REQUEST,data)
#self.tcpSock.close()
def send(self,msgType,msg):
header = pack("hhh",msgType,len(msg),self.clientUID)
msg = header+msg
self.tcpSock.send(msg)
def mainLoop(self):
while 1:
# 非阻塞模式下,当没有数据时不会阻塞
self.tcpSock.setblocking(0)
try:
data = raw_input('> ')
except EOFError: # enter key hit without any data (blank line) so ignore and continue
continue
# 数据为空,继续循环
if not data or data == '':
continue
# 输入为 exit 时,断开连接并退出
if data=='exit':
self.disconnect()
break
# 否则,发送数据
else:
self.send(TRON_CHAT,data)
if __name__ == "__main__":
cli = TronClient()
cli.connect()
在这个代码中,客户端在 receiveFromSrv
函数中设置了非阻塞模式,这样当没有数据时不会阻塞,而是继续执行 mainLoop
函数中的代码,从而实现数据的收发并行处理。