我想将ssl-support添加到基于SocketServer.TCPServer类的现有TCP服务器.所以我覆盖了TCPServer类的默认构造函数并添加了ssl.wrap_socket(...) - 调用:
class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
# See SocketServer.TCPServer.__init__
# (added ssl-support):
SocketServer.BaseServer.__init__(self, server_address,
RequestHandlerClass)
self.socket = ssl.wrap_socket(
socket.socket(self.address_family, self.socket_type),
server_side=True,
certfile='cert.pem'
)
if bind_and_activate:
self.server_bind()
self.server_activate()
Run Code Online (Sandbox Code Playgroud)
启动服务器时,不会发生错误.所以我修改了我的简单测试客户端以支持ssl:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = ssl.wrap_socket(s)
sock.connect(('192.168.1.1', 54321))
Run Code Online (Sandbox Code Playgroud)
同样没有错误发生,但连接调用阻塞.使用Ctrl + C关闭客户端时,它显示以下内容:
Traceback (most recent call last):
File "exampleClient.py", line 10, in <module>
sock.do_handshake()
File "/usr/lib/python2.6/ssl.py", line 293, in do_handshake
self._sslobj.do_handshake()
KeyboardInterrupt
Run Code Online (Sandbox Code Playgroud)
所以do_handshake在连接时会阻塞.有谁知道如何解决这个问题?我只是想使用加密的TCP连接:)
背景
我有一个简单的套接字服务器设置,我试图允许同时连接和回显数据.客户端启动多个线程,每个线程都与服务器建立自己的连接.这适用于socket.send()调用,但所有后续调用都会导致"由对等方重置连接"或"断开管道".请注意,我没有找到切换重置和损坏管道的更改.我在这里寻找解决方案,但恐怕我可能不知道该搜索什么.
我是以错误的方式解决这个问题,还是我在设置中忽略了什么?
服务器
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print "{} wrote: {}\n".format(self.client_address[0], self.data)
self.request.send(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
客户
import socket
import sys
import threading
import time
HOST, PORT = "localhost", 9999
def create_client():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
cur_thread = threading.current_thread()
sock.connect((HOST, PORT))
for x in range(55):
msg = "{}: {}\n".format(cur_thread.name, str(x))
# Connect to server and send data
print cur_thread.name + ": …Run Code Online (Sandbox Code Playgroud) 在Linux手册页中进行搜索时,我发现有关套接字中send和recv格式的内容如下:
对于发送,
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
Run Code Online (Sandbox Code Playgroud)
对于revv,
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
Run Code Online (Sandbox Code Playgroud)
但是我不确定他们想说些什么int flags。在一个示例代码中,我发现flag的值为0(零)。这是什么意思?手册页下面的那一行的含义是什么?
"The flags argument is the bitwise OR of zero or more of the following flags."
Run Code Online (Sandbox Code Playgroud)
然后是标志列表:
MSG_CONFIRM
MSG_DONTROUTE
.
.
.
etc.
Run Code Online (Sandbox Code Playgroud) 我在Linux上使用C编写了一个聊天服务器.我测试了相同的,它在性能方面工作得很好.唯一滞后的是我使用select系统调用来处理套接字描述符.由于select的限制为1024,所以最多我的聊天服务器只能同时处理1024个用户.
我知道我可以使用的另一个选项是民意调查,但与select相比,它的性能并不那么确定.
请建议我解决这种情况的最有效方法.
我正在实现一个简单的服务器,如果 3 秒内没有收到任何消息,它应该打印一条消息。
处理程序
class SingleTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
while True:
message = self.rfile.readline().strip()
print message
Run Code Online (Sandbox Code Playgroud)
服务器
class SimpleServer(SocketServer.TCPServer):
timeout = 3
def handle_timeout(self):
print "Timeout"
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
Run Code Online (Sandbox Code Playgroud)
这里我扩展了TCPServer测试超时方法。我已将timeout属性设置为3. 根据文档,如果时间过去了并且没有消息发送到客户端,handle_timeout()则调用它,在我的情况下,只打印“超时”。
BaseServer.timeout
超时持续时间,以秒为单位测量,如果不需要超时,则为“无”。如果handle_request()在超时时间内没有收到传入请求,则调用handle_timeout()方法。
我启动服务器,并观察它的输出。当我连接到它并发送一些消息时,它们通常会被打印出来。但是,如果我 3 秒或更长时间没有发送任何内容,则什么也不会发生。好像timeout和handle_timeout()尚未实施。
这种行为的根源是什么?
我正在尝试覆盖该类的serve_forever方法SocketServer.TCPServer。但是我收到一个AttributeError: MyServer instance has no attribute '_MyServer__is_shut_down'错误。
__is_shut_down在实现SocketServer.BaseServer类,应该通过被初始化__init__()的SocketServer.TCPServer。我想念什么?
import SocketServer
class MyServer(SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address,
RequestHandlerClass)
def serve_forever(self, poll_interval=0.5):
self.__is_shut_down.clear()
try:
while not self.__shutdown_request:
print "SOMETHING"
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
Run Code Online (Sandbox Code Playgroud) 我开始使用Java Socket和SocketServer类.
如上所述,我想知道Socket类默认使用哪个协议(或者它被称为).
它可能是TCP,但我找不到具体的东西,可能我忽略了一些东西.
我正在尝试使用 python 的 SocketServer 模块绑定多个服务器:
import SocketServer
from SocketServer import BaseRequestHandler
class HTTPSERVER(BaseRequestHandler):
def handle(self):
rec = self.request.recv(1024)
if rec:
self.request.send('Got something!')
launchme = SocketServer.TCPServer(('', 82),HTTPSERVER)
launchme2 = SocketServer.TCPServer(('', 81),HTTPSERVER)
launchme3 = SocketServer.TCPServer(('', 80),HTTPSERVER)
launchme.serve_forever()
print 'reached first server'
launchme2.serve_forever()
print 'reached second server'
launchme3.serve_forever()
print 'reached third server'
Run Code Online (Sandbox Code Playgroud)
当此脚本启动时,不会打印任何内容,但所有 3 个端口实际上均已打开:
root@user:/# netstat -pna|more
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2751/python
tcp 0 …Run Code Online (Sandbox Code Playgroud) 我正在阅读 python socketserver 的文档示例我正在阅读https://docs.python.org/2/library/socketserver.html
为什么在handle方法中的line中将大小指定为1024 self.request.recv(1024)。如果客户端发送的数据超过1024字节会发生什么?是否有一个循环读取 1024 字节直到套接字为空更好?我在这里复制了这个例子:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip() # why only 1024 bytes ?
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if …Run Code Online (Sandbox Code Playgroud) 在三个迭代中的每一个都需要启动 TCPServer,然后立即停止。所有 3 次都需要在端口 8000 上启动。
正如它在下面的代码中定义的那样,TCPServer 启动。但它仅在第一次迭代期间开始。其他两个迭代无法启动 TCPServer,因为端口 8000 已被在先前(第一次)迭代中启动的 TCPServer 使用。为确保端口 8000 可用,需要关闭先前启动的 TCP 服务器。
如何终止(停止)已经运行的 TCPServer?
import SimpleHTTPServer
import SocketServer
def startServer():
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
Handler.extensions_map.update({'.webapp': 'application/x-web-app-manifest+json', })
try:
httpd = SocketServer.TCPServer(("", 8000), Handler)
httpd.serve_forever()
print('httpd server has been successfully started ')
except Exception, e:
print(e)
for i in range(3):
startServer()
Run Code Online (Sandbox Code Playgroud) socketserver ×10
python ×7
sockets ×5
c ×2
linux ×2
tcp ×2
broken-pipe ×1
c++ ×1
java ×1
linux-kernel ×1
python-2.7 ×1
ssl ×1
tcpserver ×1