如何打开一个TCP套接字来监听一个连接并返回结果?

发布于 2025-01-17 05:35:36 字数 2066 浏览 1 评论 0原文

我正在尝试编写一个打开端口(戳第三方)的脚本,然后捕获并返回他们的 http 请求中有趣的部分,以便我的主线程继续。

第三方认为我们是一个http网络服务器。到目前为止,我正在尝试使用 TCPServer.SocketServer (或 http.server.HTTPServer)来执行此操作。到目前为止,对于“戳”部分,我正在使用浏览器手动点击它。但问题是:

如何将数据返回到主线程?

由于socketserver.TCPServer消耗的是一个类,而不是类的实例,所以我不知道如何将数据传回父线程。这也许就是并发编程101?我希望“返回”该值,但我想一些跨线程共享变量就可以了。

当前的代码看起来很像:

async def fourtytwo(text):
    pprint.pp(text)
    return 42


class MyTCPHandler(socketserver.BaseRequestHandler):
    data = None

    def handle(self):
        self.data = self.request.recv(1024).strip()
        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())


async def listen_for_response():
    logger = logging.getLogger(inspect.currentframe().f_code.co_name)
    logger.debug("Listening on port: %s", LISTENING_PORT)

    with socketserver.TCPServer(("localhost", LISTENING_PORT), MyTCPHandler) as server:
        server.handle_request()
        code = MyTCPHandler.data
        logger.debug("Code is: %s", code)

    logger.debug("Exiting")
    return code


async def flow(config):
    onetwo = await asyncio.gather(
        fourtytwo("one"),
        asyncio.create_task(listen_for_response()),
    )
    pprint.pp(onetwo)

输出:

DEBUG:listen_for_response:Listening on port: 4200
127.0.0.1 wrote:
b'GET / HTTP/1.1\r\nHost: localhost:4200\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: none\r\nSec-Fetch-User: ?1\r\nCache-Control: max-age=0'
DEBUG:listen_for_response:Code is: None
DEBUG:listen_for_response:Exiting
'one'
[42, None]

I'm trying to write a script which opens a port, (pokes a third party), then captures and returns the interesting part of their http request for my main thread to continue with.

The third party thinks we are an http webserver. TCPServer.SocketServer (or http.server.HTTPServer) are, so far, what I'm attempting to do this with. So far, for the "poke" part I'm manually hitting it with the browser. But the question is:

How to return the data to the main thread?

Since socketserver.TCPServer consumes a class, not an instance of a class, I do not know how to pass the data back to parent thread. This is perhaps Concurrent Programming 101? I was hoping to "return" the value, but I suppose some cross thread shared variable will do.

The current code looks a lot like:

async def fourtytwo(text):
    pprint.pp(text)
    return 42


class MyTCPHandler(socketserver.BaseRequestHandler):
    data = None

    def handle(self):
        self.data = self.request.recv(1024).strip()
        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())


async def listen_for_response():
    logger = logging.getLogger(inspect.currentframe().f_code.co_name)
    logger.debug("Listening on port: %s", LISTENING_PORT)

    with socketserver.TCPServer(("localhost", LISTENING_PORT), MyTCPHandler) as server:
        server.handle_request()
        code = MyTCPHandler.data
        logger.debug("Code is: %s", code)

    logger.debug("Exiting")
    return code


async def flow(config):
    onetwo = await asyncio.gather(
        fourtytwo("one"),
        asyncio.create_task(listen_for_response()),
    )
    pprint.pp(onetwo)

And outputs:

DEBUG:listen_for_response:Listening on port: 4200
127.0.0.1 wrote:
b'GET / HTTP/1.1\r\nHost: localhost:4200\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: none\r\nSec-Fetch-User: ?1\r\nCache-Control: max-age=0'
DEBUG:listen_for_response:Code is: None
DEBUG:listen_for_response:Exiting
'one'
[42, None]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沦落红尘 2025-01-24 05:35:36

放弃 socketserver 并直接打开套接字更容易,也许是必要的:

async def listen_once():
    """Open a TCP/IP socket on a port and capture one incoming request.

    Responds by echoing the request back in uppercase.

    Returns a list of strings like the text of the incoming request.
    """
    logger = logging.getLogger(inspect.currentframe().f_code.co_name)
    logger.debug("Listening on port: %s", LISTENING_PORT)

    s = socket.create_server(("localhost", LISTENING_PORT))
    conn, addr = s.accept()
    with conn:
        request = conn.recv(1024)
        conn.sendall(request.upper())
    s.shutdown(socket.SHUT_RD)
    s.close()

    lines = [line.decode("utf-8").strip() for line in request.split(b"\r\n")]
    for line in lines:
        logger.debug(line)
    return lines

# Start listening
listener = asyncio.create_task(listen_once())

# Do the poke
response = requests.get(uri)
logger.debug(response.text)

# Capture the request sent to the listener (which is a reaction to the poke)
await listener
request_sent_to_listener = listener.result()

It was easier, perhaps necessary, to abandon socketserver and instead open a socket directly:

async def listen_once():
    """Open a TCP/IP socket on a port and capture one incoming request.

    Responds by echoing the request back in uppercase.

    Returns a list of strings like the text of the incoming request.
    """
    logger = logging.getLogger(inspect.currentframe().f_code.co_name)
    logger.debug("Listening on port: %s", LISTENING_PORT)

    s = socket.create_server(("localhost", LISTENING_PORT))
    conn, addr = s.accept()
    with conn:
        request = conn.recv(1024)
        conn.sendall(request.upper())
    s.shutdown(socket.SHUT_RD)
    s.close()

    lines = [line.decode("utf-8").strip() for line in request.split(b"\r\n")]
    for line in lines:
        logger.debug(line)
    return lines

# Start listening
listener = asyncio.create_task(listen_once())

# Do the poke
response = requests.get(uri)
logger.debug(response.text)

# Capture the request sent to the listener (which is a reaction to the poke)
await listener
request_sent_to_listener = listener.result()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文