我正在创建一个python服务器,该服务器应该处理来自端口9090上的远程主机的连接以及仅来自端口9091上的localhost(GUI发送数据)的连接。 我认为问题出在socket.listen(backlog)中,因为这会阻止一切。 那么有一种方法可以同时运行socket1.listen(backlog)和socket2.listen(backlog)吗? 另外,创建一个用于从GUI接收数据的套接字(用Java编写)是否是一个好的,最重要的是安全的想法?
答案 0 :(得分:0)
这可以在C:Listen to multiple ports from one server
中完成和C ++:Create multiple listening sockets
所以你应该能够用Python做到这一点。
唯一能使这不安全的事情是你的服务器响应GUI而执行危险的活动,但是你可以添加代码来检查并防止攻击。
答案 1 :(得分:0)
我正在使用python2.7.3
,并且正如我的评论所述,我无法重现listen
阻止问题。
注意:
IPv4
套接字Python
的提示符,表明它没有阻止s_local
)只接受来自localhost的连接(来自其他主机的连接将失败)这是 CentOS5 计算机的代码段:
>>> import socket
>>> s_global = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s_global.bind(("", 9090))
>>> backlog = 0xFF
>>> s_global.listen(backlog)
>>> s_local = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s_local.bind(("127.0.0.1", 9091))
>>> s_local.listen(backlog)
>>>
并且在同一台机器上有一些输出:
netstat -an | grep 909
tcp 0 0 0.0.0.0:9090 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:9091 0.0.0.0:* LISTEN
如图所示,两个服务器套接字都在监听连接。
现在,如果我的环境出现问题(某些阅读显示默认情况下套接字 默认阻止),创建每个套接字后,您可以添加(如在一条评论中指明)以下行:
for s_global
s_global.setblocking(0)
用于s_local
s_local.setblocking(0)
现在为了从两个套接字接收传入连接,您应该使用Python
' s select module(用于异步IO)需要其他线程;您的服务器应用程序应该经常监听连接,例如:
TIMEOUT = 1 #seconds
terminate = False # variable to be modified externally to end the loop
listening_sockets = [s_global, s_local]
while (not terminate):
notified_socket_list = select.select(listening_sockets, [], [], TIMEOUT)[0]
for notified_socket in notified_socket_list:
incoming_socket, addr = notified_socket.accept()
handle(incoming_socket, addr)
注意:值得一提的是: epoll (select.epoll
)在性能方面比选择(select.select
)更受青睐,但我没有&#39我试过了。
现在,关于连接处理功能(句柄):如果您的服务器仅用于教育目的,您可以保持原样,但如果您的服务器设计为同时接受大量来自/到每个客户的连接和大量数据交换,您应该在单独的线程中处理每个连接(这是一个不适用于Python
的一般建议,因为它GIL,有时线程只会降低速度)/ 进程,如同SocketServer.py - part of Python's standard library中所做的那样。
@ Edit1 - 回复第1条评论:
很简单,你所要做的就是修改一下内部 for
循环:
for notified_socket in notified_socket_list:
incoming_socket, addr = notified_socket.accept()
if notified_socket == s_global:
handle_global(incoming_socket, addr)
else:
handle_local(incoming_socket, addr)
或者您可以使用我的原始解决方案并区分句柄中的连接:addr
参数包含套接字连接到的(本地)端口;您可以测试它,并根据其值(9090或9091)以不同方式处理连接。