首页 文章

Python,同时在两个套接字上进行侦听

提问于
浏览
0

我正在制作一个python服务器,它应该处理来自端口9090上的远程主机的连接以及仅来自端口9091上的localhost(GUI发送数据)的连接 . 我认为问题出在socket.listen(backlog)中,因为这会阻止所有内容 . 那么有一种方法可以同时运行socket1.listen(backlog)和socket2.listen(backlog)吗?另外,创建一个用于从GUI接收数据的套接字(用Java编写)是否是一个好的,最重要的是安全的想法?

2 回答

  • 0

    这可以在C中完成:Listen to multiple ports from one server

    和C:Create multiple listening sockets

    所以你应该能够用Python做到这一点 .

    唯一能使这不安全的是你的服务器响应GUI执行危险的活动,但你可以添加代码来检查和防止黑客攻击 .

  • 0

    我正在使用 python2.7.3 ,并且如我的评论中所述,我无法重现 listen 阻止问题 . 笔记:

    • 为了简单起见我只使用 IPv4 套接字

    • 我包括 Python 's prompter in the code to show that it didn' t块

    • 关于最终的安全问题:监听9091的套接字( 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
    

    如图所示,两个服务器套接字都在监听连接 .

    现在,如果我的环境出现问题(某些读数显示默认情况下套接字默认是阻塞的), after creating each socket ,您可以添加(如一条注释中所指定的)以下行:

    • for s_global
    s_global.setblocking(0)
    
    • for s_local
    s_local.setblocking(0)
    

    现在为了从两个套接字 receive incoming connections ,您应该使用 Pythonselect module(用于异步IO) with no need for other threads ;您的服务器应用程序应该经常监听连接,例如:

    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 ),但我还没有尝试过 .

    现在,关于连接处理功能( handle ):如果您的服务器仅用于教育目的,您可以保持原样,但如果您的服务器设计为接受大量的同时连接和大量数据交换客户端,你应该在一个单独的 thread 中处理每个连接(这是一个不适用于 Python 的一般建议,因为它的GIL,有时线程只会减慢速度)/ processSocketServer.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)
    

    或者您可以使用我的原始解决方案并在 handle 中区分连接: addr 参数包含套接字连接到的(本地)端口;您可以对其进行测试,并根据其值(9090或9091)以不同方式处理连接 .

相关问题