- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我的代码基本上需要启动一个带有客户端的简单聊天服务器。服务器和客户端可以相互来回交谈的地方。我已经得到了正确实现的一切,但我无法弄清楚如何在我完成时关闭服务器。 (我知道它是 ss.shutdown()
)。
我想根据两者之间共享的关键字(例如 “bye”
)立即结束,但我不知道是否可以通过某种方式向我的 SocketServer
从 BaseRequestHandler
到 shutdown()
每当它收到消息时。
最终,我的目标是结合 Tkinter
来制作一个 GUI,但我想先让其他一切正常工作,这是我第一次在 Python 中处理套接字。
from sys import argv, stderr
from threading import Thread
import socket
import SocketServer
import threading
import sys
class ThreadedRecv(Thread):
def __init__(self,socket):
Thread.__init__(self)
self.__socket = socket
self.__message = ''
self.__done = False
def recv(self):
while self.__message.strip() != "bye" and not self.getStatus():
self.__message = self.__socket.recv(4096)
print 'received',self.__message
self.setStatus(True)
def run(self):
self.recv()
def setStatus(self,status):
self.__done = status
def getStatus(self):
return self.__done
class ThreadedSend(Thread):
def __init__(self,socket):
Thread.__init__(self)
self.__socket = socket
self.__message = ''
self.__done = False
def send(self):
while self.__message != "bye" and not self.getStatus():
self.__message = raw_input()
self.__socket.send(self.__message)
self.setStatus(True)
def run(self):
self.send()
def setStatus(self,status):
self.__done = status
def getStatus(self):
return self.__done
class HostException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class EchoServer(SocketServer.BaseRequestHandler):
def setup(self):
print self.client_address, 'is connected!'
self.request.send('Hello ' + str(self.client_address) + '\n')
self.__done = False
def handle(self):
sender = ThreadedSend(self.request)
recver = ThreadedRecv(self.request)
sender.start()
recver.start()
while 1:
if recver.getStatus():
sender.setStatus(True)
break
if sender.getStatus():
recver.setStatus(True)
break
def finish(self):
print self.client_address, 'disconnected'
self.request.send('bye client %s\n' % str(self.client_address))
self.setDone(True)
def setDone(self,done):
self.__done = done
def getDone(self):
return self.__done
def setup(arg1, arg2, arg3):
server = False
defaultPort,defaultHost = 2358,"localhost"
hosts = []
port = defaultPort
serverNames = ["TRUE","SERVER","S","YES"]
arg1 = arg1.upper()
arg2 = arg2.upper()
arg3 = arg3.upper()
if arg1 in serverNames or arg2 in serverNames or arg3 in serverNames:
server = True
try:
port = int(arg1)
if arg2 != '':
hosts.append(arg2)
except ValueError:
if arg1 != '':
hosts.append(arg1)
try:
port = int(arg2)
if arg3 != '':
hosts.append(arg3)
except ValueError:
if arg2 != '':
hosts.append(arg2)
try:
port = int(arg3)
except ValueError:
if arg3 != '':
hosts.append(arg3)
port = defaultPort
for sn in serverNames:
if sn in hosts:
hosts.remove(sn)
try:
if len(hosts) != 1:
raise HostException("Either more than one or no host "+ \
"declared. Setting host to localhost.")
except HostException as error:
print error.value, "Setting hosts to default"
return (server,defaultHost,port)
return (server,hosts[0].lower(),port)
def main():
bufsize = 4096
while len(argv[1:4]) < 3:
argv.append('')
settings = setup(*argv[1:4])
connections = (settings[1],settings[2])
print connections
if not settings[0]:
try:
mySocket = socket.socket(socket.AF_INET,\
socket.SOCK_STREAM)
except socket.error, msg:
stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(1)
try:
mySocket.connect(connections)
except socket.error, msg:
stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(2)
message = ""
print "Enter a message to send to the server. "+\
"Enter \"bye\" to quit."
sender = ThreadedSend(mySocket)
recver = ThreadedRecv(mySocket)
sender.start()
recver.start()
while 1:
if sender.getStatus():
recver.setStatus(True)
break
if recver.getStatus():
sender.setStatus(True)
break
else:
xserverhandler = EchoServer
serversocket = SocketServer.ThreadedTCPServer(\
connections,xserverhandler)
server_thread = Thread(target = serversocket.serve_forever)
server_thread.setDaemon(True)
server_thread.start()
# I would like to shut down this server whenever
# I get done talking to it.
"""while 1:
if xserverhandler.getDone():
print 'This is now true!'
serversocket.shutdown()
break"""
if __name__ == '__main__':
main()
是的,我知道 setup() 现在对于 try 和 catch 来说是一个糟糕的函数,但它现在可以工作,所以我打算稍后修复它。
我的问题基本上是:如何让服务器根据收到的消息实际结束?如果可能,有没有办法在 Request Handler 启动后访问它?
最佳答案
请修复您的代码以使其正常工作,并提供一些使用方法。你需要添加
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
因为 SocketServer 实际上并不包含该类(至少在我的 2.6 或 2.7 版本中不包含)。相反,它是来自 SocketServer definition 的示例.
请包括一个如何启动/使用代码的示例。在这种情况下,要启动服务器,您需要执行以下操作:
ss.py SERVER localhost 8001
和客户端作为
ss.py localhost 8001
如果您这样做,那么您将无法执行 server_thread.setDaemon(True),因为没有其他线程在运行,这意味着服务器将立即退出。
完成后,解决方案是在 EchoServer.handle 方法的 self.server.shutdown() insdie 中添加一个(或两个)调用,例如:
while 1:
if recver.getStatus():
sender.setStatus(True)
self.server.shutdown()
break
但是,我无法让它发挥作用,我认为这是因为我继承了错误的东西,或者对你所做的事情猜错了。
你应该做的是搜索其他用 Python 做过聊天服务器的人。使用谷歌我找到了http://www.slideshare.net/didip/socket-programming-in-python当然还有其他人。
此外,如果您打算混合使用 GUI 和线程编程,那么您应该查看基于此的示例。当我搜索“tkinter chat”时,有很多点击。另外,您可能想看看 twisted,它已经解决了很多这样的问题。
什么问题?嗯,例如,您可能需要一个 SO_REUSEADDR 套接字选项。
关于Python 访问 BaseRequestHandler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1578932/
我的代码基本上需要启动一个带有客户端的简单聊天服务器。服务器和客户端可以相互来回交谈的地方。我已经得到了正确实现的一切,但我无法弄清楚如何在我完成时关闭服务器。 (我知道它是 ss.shutdown(
这是我玩过的代码,但每次我犯错我都无法重新启动它。它对我说端口/套接字已被使用这是第一个问题第二个在我的 MyTCPHandler 中,我怎么知道使用的端口?这是我的代码: # MetaProject
我一直在使用 SocketServer.TCPServer 和 SocketServer.BaseRequestHandler 基类开发 Python 服务器。我正在使用主机“localhost”和端
小问题 使用下面的示例,是否有一种 Pythonic 方式可以与 BaseRequestHandler 类共享 my_object 的实际实例? 背景 根据定义,BaseRequestHandler
这是个问题。我的主要工作是:将“s”对象传递给 TestRequestHandler 类中的“handle”方法。我的第一步是:通过“点”方法将“s”对象传递给 TestServer 类,但我卡在这里
我正在用 Python 编写一个客户端/服务器应用程序,我发现有必要为来自客户端的每个请求建立一个到服务器的新连接。我的服务器只是从 TCPServer 继承,我从 BaseRequestHandle
我是一名优秀的程序员,十分优秀!