我希望标题合适。如果没有,请提出替代方案。我正在与以下Python客户班类合作。
import Queue
import socket
import struct
import threading
import time
class ClientCommand(object):
CONNECT, SEND, RECEIVE, CLOSE = range(4)
def __init__(self, type, data=None):
self.type = type
self.data = data
class ClientReply(object):
ERROR, SUCCESS = range(2)
def __init__(self, type, data = None):
self.type = type
self.data = data
class SocketClientThread(threading.Thread):
def __init__(self, cmd_q = Queue.Queue(), reply_q = Queue.Queue()):
super(SocketClientThread, self).__init__()
self.cmd_q = cmd_q
self.reply_q = reply_q
self.alive = threading.Event()
self.alive.set()
self.socket = None
#self.stopped = False
self.handlers = {
ClientCommand.CONNECT: self._handle_CONNECT,
ClientCommand.CLOSE: self._handle_CLOSE,
ClientCommand.SEND: self._handle_SEND,
ClientCommand.RECEIVE: self._handle_RECEIVE
}
def run(self):
while self.alive.isSet():
#while not self.stopped:
try:
cmd = self.cmd_q.get(True, 0.1)
self.handlers[cmd.type](cmd)
except Queue.Empty as e:
continue
def stop(self):
self.alive.clear()
def join(self, timeout=None):
self.alive.clear()
threading.Thread.join(self, timeout)
def _handle_CONNECT(self, cmd):
try:
self.socket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((cmd.data[0], cmd.data[1]))
self.reply_q.put(self._success_reply())
except IOError as e:
self.reply_q.put(self._error_reply(str(e)))
def _handle_CLOSE(self, cmd):
self.socket.close()
reply = ClientReply(ClientReply.SUCCESS)
self.reply_q.put(reply)
def _handle_SEND(self, cmd):
try:
print "about to send: ", cmd.data
self.socket.sendall(cmd.data)
print "sending data"
self.reply_q.put(self._success_reply())
except IOError as e:
print "Error in sending"
self.reply_q.put(self._error_reply(str(e)))
def _handle_RECEIVE(self, cmd):
try:
#TODO Add check for len(data)
flag = True
while flag:
print "Receiving Data"
data = self._recv_n_bytes()
if len(data) != '':
self.reply_q.put(self._success_reply(data))
if data == "Stop":
print "Stop command"
flag = False
except IOError as e:
self.reply_q.put(self._error_reply(str(e)))
def _recv_n_bytes(self):
data = self.socket.recv(1024)
return data
def _error_reply(Self, errstr):
return ClientReply(ClientReply.ERROR, errstr)
def _success_reply(self, data = None):
return ClientReply(ClientReply.SUCCESS, data)
我的主要脚本代码 -
import socket
import time
import Queue
import sys
import os
from client import *
sct = SocketClientThread()
sct.start()
host = '127.0.0.1'
port = 1234
sct.cmd_q.put(ClientCommand(ClientCommand.CONNECT, (host, port)))
try:
while True:
sct.cmd_q.put(ClientCommand(ClientCommand.RECEIVE))
reply = sct.reply_q
tmp = reply.get(True)
data = tmp.data
if data != None:
if data != "step1":
//call function to print something
else:
// call_function that prints incoming data till server stops sending data
print "Sending OK msg"
sct.cmd_q.put(ClientCommand(ClientCommand.SEND, "Hellon"))
print "Done"
else:
print "No Data"
except:
#TODO Add better error handling than a print
print "Server down"
所以这是问题。线程启动并调用接收处理程序后,我将获得一些数据,如果该数据不是" step1",我只会调用函数(另一个脚本)以打印它。
但是,如果数据为" step1",我将调用一个函数,然后将继续打印服务器接下来发送的任何数据,直到服务器发送"停止"消息。在这一点上,我突破了"接收处理程序",并尝试向服务器发送"确定"消息。
但是,一旦我脱离"接收处理程序",它就会自动再次调用该功能。因此,当我试图发送一条消息时,客户端再次等待服务器的数据。因此,由于再次调用"接收器函数","发送函数"块。
我似乎不明白如何在接收和发送之间切换。我在这里的方法有什么问题?我应该如何解决这个问题?我需要重写代码以有两个单独的线程以发送和接收?
如果您需要更多详细信息,请在您决定无缘无故地提出问题之前让我知道。
但是,一旦我脱离了"接收处理程序", 自动调用该功能。
这是因为您在接收到的每个数据块的while True
循环中调用sct.cmd_q.put(ClientCommand(ClientCommand.RECEIVE))
,i。e。对于" step1"之前的每个数据,一个命令将调用"接收处理程序"(本身循环直到"停止")被放入客户端命令队列中,然后当然在发送命令之前执行这些命令。如果您在此while True
循环之前将接收电话打开,您的方法可以工作。
错误是
if msgid != "step1":
NameError: name 'msgid' is not defined
而不是
#TODO Add better error handling than a print
print "Server down"
你有更好的书面
raise
并立即发现它。