【问题标题】:Using Processes as Threads with Networking in Python在 Python 中使用进程作为线程和网络
【发布时间】:2013-03-04 22:32:01
【问题描述】:

基本上,我的想法是编写某种基本服务器,我可以在其中连接到我的计算机,然后远程运行命令。这似乎不是什么大问题。但后来我有了一个好主意,下一步逻辑上是添加某种线程,这样我就可以产生多个连接。

我读到,由于 GIL,multiprocessing.Process 将是尝试执行此操作的最佳选择。我不完全理解线程,很难找到关于它的好的文档;所以我只是扔东西并试图弄清楚它是如何工作的。

嗯,看来我可能已经接近正确了;但我有一种感觉,我几乎不可能正确地做到这一点。我的程序现在确实允许多个连接,而当我第一次开始使用线程时它没有;但是一旦建立连接,然后建立另一个连接,第一个连接就不再能够向服务器发送命令。如果有人能给我任何帮助,或者指出我需要学习和理解的正确方向,我将不胜感激。

这是我的代码:

class server:
    def __init__(self):
        self.s = socket.socket()
        try:
            self.s.bind(("",69696))
            self.s.listen(1)
        except socket.error,(value,message):
            if self.s:
                self.s.close()
    def connection(self):
        while True:
            client , address = self.s.accept()

            data = client.recv(5)
            password = 'hello'
            while 1:
                if data == password:
                    subprocess.call('firefox')
                    client.close()
                else:
                    client.send('wrong password')
                    data = client.recv(5)
            p = Process(target=x.connection())
            p.start()
x = server()

if __name__ == '__main':
    main()

【问题讨论】:

  • 这是在什么平台上运行的? Unix/Linux?还是窗户?
  • PS:如果条件data == password 为真,那么while 1: 循环将无限进行。它将继续无限地产生firefox进程。您可能想在client.close() 之后添加break
  • 我主要是在 Linux/Ubuntu 上尝试过,但我也在 VirtualBox Windows 7 上尝试过。
  • 是的,我知道,我添加它的原因是为了确保我可以检查我是否因为正确的原因而断开连接。或者好吧,我想断开连接的原因,如果这有意义的话。不过我没想过添加 break,会的。
  • 请考虑twistedmatrix.com,以避免解决许多与编写网络应用程序相关的无聊问题。

标签: python multithreading networking process


【解决方案1】:

好吧,这个答案仅适用于您使用的是 unix 或类似 unix 的操作系统(Windows 没有我们使用的 os.fork())。

在 unix 平台上执行这些操作的最常见方法之一是 fork 一个新进程来处理客户端连接,同时主进程继续侦听请求。

以下是可以处理多个同时连接的简单回显服务器的代码。您只需修改handle_client_connection() 以满足您的需求

import socket
import os

class ForkingServer:
    def serve_forever(self):
        self.s = socket.socket()
        try:
            self.s.bind(("", 9000))
            self.s.listen(1)
        except socket.error, (value,message):
            print "error:", message
            if self.s:
                self.s.close()
            return

        while True:
            client,address = self.s.accept()
            pid = os.fork()
            # You should read the documentation for how fork() works if you don't
            # know it already
            # The short version is that at this point in the code, there are 2 processes
            # completely identical to each other which are simulatenously executing
            # The only difference is that the parent process gets the pid of the child
            # returned from fork() and the child process gets a value of 0 returned
            if pid == 0:
                # only the newly spawned process will execute this
                self.handle_client_connection(client, address)
                break
            # In the meantime the parent process will continue on to here
            # thus it will go back to the beginning of the loop and accept a new connection

    def handle_client_connection(self, client,address):
        #simple echo server
        print "Got a connection from:", address
        while True:
            data = client.recv(5)
            if not data:
                # client closed the connection
                break
            client.send(data)
        print "Connection from", address, "closed"


server = ForkingServer()
server.serve_forever()

【讨论】:

  • 水越来越深了!首先是线程,然后是进程更好,现在是 os.fork()。这么多选择,我该怎么决定学什么!但是感谢您的回复,这很好用,而且看起来比线程更容易混淆。
  • 您可能可以通过更便携的方式实现与os.fork()Process() 相同的效果(因为os.fork() 在Windows 上不存在)。但是,我最熟悉os.fork(),现在是凌晨 2 点,所以我不想继续就我没有经验的事情提供建议:)
  • 我完全明白了,反正知道 os.fork() 似乎很好,它很简单,没有太多的包袱。我仍然会尝试在 Process() 上找到一些好的文档,但现在这很好。再次感谢!
  • 很高兴能帮上忙 :)
  • @RussAdams 我建议查看PyMOTW
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多