Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
构建异步套接字教程:如何连接到python中的侦听套接字?_Python_Asynchronous_Asyncore - Fatal编程技术网

构建异步套接字教程:如何连接到python中的侦听套接字?

构建异步套接字教程:如何连接到python中的侦听套接字?,python,asynchronous,asyncore,Python,Asynchronous,Asyncore,python 2.6 视窗7 我正在尝试编写一个尽可能简单的教程,介绍如何编写协作多任务程序。作为一个示例应用程序,我用python的asyncore后端编写了一个聊天服务器。我认为这将是社区的宝贵资源。然而,我还没有让它工作,因此这篇文章 结构如下。ChatServer的实例在远程计算机上运行。它的套接字监听远程端口。当它检测到传入连接时,会生成一个ChatHandler实例来调解与该连接的通信。现在,那个连接是谁?在用户的本地机器上,我们运行ChatDaemon的一个实例。这家伙监听本地端口

python 2.6 视窗7

我正在尝试编写一个尽可能简单的教程,介绍如何编写协作多任务程序。作为一个示例应用程序,我用python的asyncore后端编写了一个聊天服务器。我认为这将是社区的宝贵资源。然而,我还没有让它工作,因此这篇文章

结构如下。ChatServer的实例在远程计算机上运行。它的套接字监听远程端口。当它检测到传入连接时,会生成一个ChatHandler实例来调解与该连接的通信。现在,那个连接是谁?在用户的本地机器上,我们运行ChatDaemon的一个实例。这家伙监听本地端口。当你这样和他联系的时候

import socket
s = socket.socket()
s.connect(('localhost',LOCAL_PORT))
他检测到连接并生成两个东西,一个LocalListener和一个连接。该连接连接到服务器,从上面回答了我们的问题。LocalListener只是等待来自用户的数据。如果你发送数据

s.send("Hello, world!")
LocalListener将其拾取,并将其提供给连接,然后连接将其发送到ChatServer。然后,服务器将数据放入每个ChatHandler的缓冲区中,以发送到所有连接的客户端。当连接接收到该数据时,它将其传递给守护进程,守护进程将其打印到屏幕上

(守护进程层似乎过于复杂,但如果没有它,您必须执行其他复杂的操作,以防止asyncore的select()循环中出现热循环,同时保持用户发送数据的低延迟。我不想走这条路。)

问题是似乎没有建立到守护进程的连接。我的具体步骤是

在一个python会话中

d = ChatDaemon('localhost')
d.start()
import socket
s = socket.socket()
s.connect(('localhost',7668))
当我这样做时,我会看到消息“Chat daemon绑定到'localhost:7668',正如预期的那样

在另一个python会话中

d = ChatDaemon('localhost')
d.start()
import socket
s = socket.socket()
s.connect(('localhost',7668))
当我这样做时,我没有看到“Get new local connection”行被打印出来

我编辑了我的etc/hosts文件,将“localhost”映射到127.0.0.1,并安装了Microsoft环回适配器

EDIT:我已经发现并修复了这个问题。下面的代码现在应该可以作为一个使用asyncore的非常简单的聊天实现

这是来源

import asyncore
import socket
import sys

LOCAL_HOST = 'localhost'
LOCAL_PORT = 7668
REMOTE_HOST = 'localhost'
REMOTE_PORT = 7667

class LocalListener(asyncore.dispatcher):
    """Receive data from user, putting into cxn's buffer"""
    def __init__(self, sock, cxn):
        self.cxn = cxn
        asyncore.dispatcher.__init__(self, sock)

    def writable(self):
        return False

    def readable(self):
        return True

    def handle_read(self):
        data = self.recv(4096)
        if data:
            self.cxn.buf = self.cxn.buf + data

class Connection(asyncore.dispatcher):
    """Mediates between user and server"""
    def __init__(self, host, port, master):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host,port))
        self.buf=""

    def writable(self):
        return len(self.buf) > 0

    def readable(self):
        return True

    def handle_read(self):
        data = self.recv(4096)
        if data:
            self.master.newMessage(data)

    def handle_write(self):
        sent = self.send(self.buf)
        self.buf = self.buf[sent:]

class ChatDaemon(asyncore.dispatcher):
    """Listen for local connections and dispatch in/out data"""
    ADDRESS_FAMILY = socket.AF_INET
    SOCKET_TYPE = socket.SOCK_STREAM
    def __init__(self, remoteHost, remotePort=REMOTE_PORT,
                 localHost=LOCAL_HOST, localPort=LOCAL_PORT):
        self.remoteHost = remoteHost
        self.remotePort = remotePort
        self.localHost = localHost
        self.localPort = localPort
        self.buffer = ""
        asyncore.dispatcher.__init__(self)

    def writable(self):
        return False

    def readable(self):
        return True

    def newMessage(self, data):
        print data

    def start(self):
        """Listen for user connection on local port"""
        self.create_socket(self.ADDRESS_FAMILY, self.SOCKET_TYPE)
        print("Chat deamon binding to '%s': %s"%(self.localHost,self.localPort))
        self.bind((self.localHost,self.localPort))
        self.listen(1)
        asyncore.loop()

    def handle_accept(self):
        """Spawn local reader and remote reader/writer"""
        print "Got new local connection"
        (connSock, localAddress) = self.accept()
        print("New connection address is %s"%localAddress)
        #Make a server connection
        cxn = Connection(self.remoteHost, self.remotePort, self)
        #Connect to local user
        LocalListener(connSock, cxn)

### SERVER ###

class ChatHandler(asyncore.dispatcher):
    def __init__(self, sock, map, server):
        self.server = server
        self.buffer = ''
        asyncore.dispatcher.__init__(self, sock, map)

    def writable(self):
        return len(self.buffer) > 0

    def readable(self):
        return True

    def handle_read(self):
        """Notify server of any new incoming data"""
        data = self.recv(4096)
        if data:
            self.server.newMessage(data, self)

    def handle_write(self):
        """send some amount of buffer"""
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]

class ChatServer(asyncore.dispatcher):
    """Receive and forward chat messages

    When a new connection is made we spawn a dispatcher for that
    connection.
    """
    ADDRESS_FAMILY = socket.AF_INET
    SOCKET_TYPE = socket.SOCK_STREAM
    def __init__(self, host=REMOTE_HOST, port=REMOTE_PORT):
        self.map = {}
        self.address = (host,port)
        self.clients = []
        asyncore.dispatcher.__init__(self, map=self.map)

    def serve(self):
        """Bind to socket and start asynchronous loop"""
        self.create_socket(self.ADDRESS_FAMILY, self.SOCKET_TYPE)
        self.bind(self.address)
        self.listen(1)
        asyncore.loop(map=self.map)

    def writable(self):
        return False

    def readable(self):
        return True

    def newMessage(self, data, fromWho):
        """Put data in all clients' buffers"""
        for client in self.clients:
            client.buf = client.buf + data

    def handle_accept(self):
        """Deal with newly accepted connection"""
        print 'got new connection'
        (connSock, clientAddress) = self.accept()
        self.clients.append(ChatHandler(connSock, self.map, self))

问题是在ChatDaemon中,我忘记了可读写的“return”关键字