我已经基于这里的示例创建了一个运行ThreadingTCPServer的简单测试应用程序(Python 2.6.1).如果客户端发送命令"bye",我想关闭服务器并从应用程序中彻底退出.退出部分工作正常,但当我尝试重新运行应用程序时,我得到:
socket.error: [Errno 48] Address already in use
Run Code Online (Sandbox Code Playgroud)
我尝试了这里给出的解决方案来设置套接字选项,但这似乎没有帮助.我已尝试各种方法关闭服务器,但总是得到相同的错误.
知道我做错了什么吗?
import SocketServer
import socket
import sys
import threading
import time
class RequestHandler(SocketServer.BaseRequestHandler):
def setup(self):
print("Connection received from %s" % str(self.client_address))
self.request.send("Welcome!\n")
def handle(self):
while 1:
data = self.request.recv(1024)
if (data.strip() == 'bye'):
print("Leaving server.")
self.finish()
self.server.shutdown()
# None of these things seem to work either
#time.sleep(2)
#del self.server.socket
#self.server.socket.shutdown(socket.SHUT_WR)
#self.server.socket.close()
#self.server.server_close()
break
def finish(self):
self.request.send("Goodbye! Please come back soon.")
if __name__ == "__main__":
server = …Run Code Online (Sandbox Code Playgroud) 我一直在玩Python的SocketServer:
#!/usr/bin/python
import SocketServer
class EchoHandler(SocketServer.BaseRequestHandler):
def handle(self):
data=self.request.recv(1024)
self.request.send(data)
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), TCPEchoServer)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
通过阅读源代码,我知道作为参数接收并RequestHandler.__init__()在.requestself.request
在哪里可以找到该request对象的规格?
我正在学习如何在python中使用套接字,并且经常当我的程序崩溃或者我在Ctrl + C时服务器套接字以某种方式继续监听端口.这显然会阻止程序在再次启动时监听该端口,因此我必须不断更改它.
我猜我需要在某处做socket.close(),但在哪里?
简短问题
使用下面的示例,是否有一种Pythonic方法my_object与BaseRequestHandler类共享实际实例?
背景
根据定义,BaseRequestHandler类为每个请求创建一个新实例.因此,我正在努力寻找一种解决方案来解决如何将handle()函数中的数据传回ProtocolInterface实例的问题.请注意,如果我需要执行handle()除print到stdout以外的操作,这可能是错误的方法.
在这个时间点,我不相信全局变量会my_object传递,因为传入并且预计会经常更改(这就是为什么handle()需要看到它.要查看示例客户端(发送伪造数据),请参阅我的其他SO问题.我认为我面临的最大问题是套接字服务器在后台线程中运行.
我想做什么的例子
class ProtocolHandler(SocketServer.BaseRequestHandler):
def handle(self):
while(1):
self.data = self.request.recv(1024)
if self.data == '':
break
self.request.send("Success")
self.my_object.success = True# <--- How can I share my_object's instance?
class ProtocolInterface():
def __init__(self, obj, host='127.0.0.1', port=8000, single_connection=False):
self.my_object = obj # <--- This ideally is the same instance seen in ProtocolHandler
self.host = host
self.port = port
# Create the socket server to process in …Run Code Online (Sandbox Code Playgroud) 在使用标准库时,我发现python2和python3之间存在一些奇怪的区别.如果我尝试在python2中捕获信号,而TCPServer在不同的线程中运行,则信号不会被处理,但在python3中它确实如此.
这是一个重现问题的脚本
import signal
import threading
import sys
if sys.version_info > (3,0):
from socketserver import TCPServer, BaseRequestHandler
else:
from SocketServer import TCPServer, BaseRequestHandler
def shutdown(signum, frame):
print("Shutting down server thread")
server.shutdown()
server = TCPServer(
('127.0.0.1', 7654),
BaseRequestHandler
)
signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)
server_thread = threading.Thread(target=server.serve_forever)
print("Starting server thread")
server_thread.start()
print("Waiting for server thread to shut down")
server_thread.join()
print("Server thread terminated")
Run Code Online (Sandbox Code Playgroud)
这是python3的输出:
Starting server thread
Waiting for server thread to shut down
^CShutting down server thread
Server thread terminated
Run Code Online (Sandbox Code Playgroud)
这是来自python2:
Starting …Run Code Online (Sandbox Code Playgroud) 我对如何正确关闭我正在使用的非常简单的服务器感到困惑。
我想这应该足够了:
#!/usr/bin/python
import signal
import myhandler
import SocketServer
def terminate(signal, frame):
print "terminating on %s at %s"
server.shutdown()
if __name__ == "__main__":
signal.signal(signal.SIGTERM, terminate)
server = SocketServer.TCPServer(("localhost", 9999), myhandler.MyHandler)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
服务器工作正常,但是当我向它抛出 SIGTERM 时,它只会打印terminating on 15 at ...但不会真正关闭(即关闭所有套接字并退出)。
现在 pydoc 解释了它
#!/usr/bin/python
import signal
import myhandler
import SocketServer
def terminate(signal, frame):
print "terminating on %s at %s"
server.shutdown()
if __name__ == "__main__":
signal.signal(signal.SIGTERM, terminate)
server = SocketServer.TCPServer(("localhost", 9999), myhandler.MyHandler)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
但这就是我迷失的地方,因为我什至无法理解线程编程。现在我只需要一个简单的 TCP 回显服务器,我可以killall随时启动该服务器(由于剩余的监听套接字而现在失败)。
那么实现这一目标的正确方法是什么?
在异步(线程)SocketServer http://docs.python.org/2/library/socketserver.html的示例中,启动服务器线程(称为 server_thread),为每个请求启动新线程。由于捕获键盘中断时出现一些问题,我开始寻找类似的代码,发现不使用服务器线程时没有明显的区别,但 ctrl-c 实际上有效。
尽管我的代码有效,但我很想知道
1)为什么在使用 server_thread 时,简单的“尝试”捕获 KeyboardInterrupt 不起作用?
2)与我的稍微简单的示例相比,示例中的 server_thread 有什么好处?
从python SocketServer示例来看,在try中捕获键盘中断不起作用:
if __name__ == "__main__":
server = ThreadedTCPServer(serverAddr, SomeCode)
<snip>
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
Run Code Online (Sandbox Code Playgroud)
我的更简单的例子是 ctrl-c 有效。
if __name__ == "__main__":
server = ThreadedTCPServer(serverAddr, SomeCode)
try:
server.serve_forever()
print "ctrl-c to exit"
except KeyboardInterrupt:
print "interrupt received, exiting"
server.shutdown()
Run Code Online (Sandbox Code Playgroud) 我需要使用 python 将字符串发送到本地主机上的特定端口。
我可以通过在命令行上使用 socat 来实现这一点,如下所示:
cat <text file containing string to send> | socat stdin tcp-connect:127.0.0.1:55559
Run Code Online (Sandbox Code Playgroud)
我不想将 socat 命令作为子命令运行,所以我想知道如何使用 python 模块使其工作。
我尝试使用套接字失败了。下面是我使用的一个脚本,它没有达到预期的效果。
import socket
HOST, PORT = "127.0.0.1", 55559
jsonString = '{"name":"VideoStreamStatus","parameters":{"name":"video_0_0"}}'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to server and send data
print "Attempting connection"
sock.connect((HOST, PORT))
print "Sending json string"
sock.sendall(jsonString)
print "String sent"
finally:
sock.close()
print "Sent: {}".format(jsonString)
Run Code Online (Sandbox Code Playgroud)
python 脚本执行时没有任何错误,但对接收 socat 数据的进程没有任何影响。Python脚本输出如下:
Attempting connection
Sending json string
Sent: {"name":"VideoStreamStatus","parameters":{"name":"video_0_0"}}
Run Code Online (Sandbox Code Playgroud)
我在套接字脚本中做错了什么,或者我可以在 Python 中使用不同的方法吗?我很感激任何建议。谢谢。
编辑:我尝试向其发送字符串的服务器是 C++ 程序的一部分,该程序使用 …
我有一个基于的服务器ThreadingTCPServer.现在我想要为该服务器添加SSL支持.没有SSL它工作正常,但使用SSLv3我无法将客户端连接到服务器,它总是抛出一个异常:Error 111 Connection Refused.错误是该端口上没有SSL服务器.
我根据Stackoverflow上的示例添加了SSL支持.这是我的代码:
服务器:
class BeastServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
SocketServer.BaseServer.__init__(self, server_address,
RequestHandlerClass)
ctx = SSL.Context(SSL.SSLv3_METHOD)
cert = 'server.pem'
key = 'key.pem'
ctx.use_privatekey_file(key)
ctx.use_certificate_file(cert)
self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
self.socket_type))
if bind_and_activate:
#self.server_bind()
#self.server_a
Run Code Online (Sandbox Code Playgroud)
客户:
class Client(object) :
def verbinden (self, ip_) :
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_SSLv3, ca_certs='server.pem')
ssl_sock.connect((ip_, 10012))
return ssl_sock
Run Code Online (Sandbox Code Playgroud)
密钥和证书文件是使用开放SSL创建的.我希望有人能告诉我问题是什么.
谢谢你的帮助
最好的问候帕特里克
我有一个简单的python tcp服务器(我正在使用SocketServer类)的问题,必须从Java客户端接收数据.
这里是服务器端代码:
class ServerRequestHandler(SocketServer.BaseRequestHandler):
[...]
def handle(self):
requestCode = struct.unpack('>i', self.request.recv(4))[0]
[...]
[...]
Run Code Online (Sandbox Code Playgroud)
这里有客户:
addr = InetAddress.getByName(hostname);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
clientSocket = new Socket();
clientSocket.connect(sockaddr, timeoutMs);
clientSocketDataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
int requestCode = 1;
clientSocketDataOutputStream.writeInt(requestCode);
clientSocketDataOutputStream.flush();
Run Code Online (Sandbox Code Playgroud)
我启动Python服务器然后尝试执行必须向服务器发送整数的客户端.
在服务器端,Python引发异常,因为该recv(4)函数不读取4个字节,它只返回一个字节.
我的java客户端实际上正确地发送了4个字节,如果我尝试调用recv(1)4次它正确地读取4个字节.
我试着编写一个Python客户端来执行我的java客户端的相同操作,在这种情况下服务器recv(4)运行良好.
如何解决这个问题呢?我想实现一个简单的python buffered reader function,它逐字节地从socket读取,但我确信存在一个更智能的解决方案.
python ×10
socketserver ×10
sockets ×3
java ×1
namespaces ×1
python-2.7 ×1
signals ×1
socat ×1
ssl ×1
tcp ×1