python asyncore服务器只向一个袜子发送数据

时间:2013-07-30 19:05:43

标签: python sockets send asyncore

我必须像我一样只将数据发送到连接?

服务器:

import asyncore, socket, threading

class EchoHandler(asyncore.dispatcher_with_send):
    def __init__(self,sock):
        asyncore.dispatcher.__init__(self,sock=sock);
        self.out_buffer = ''

    def handle_read(self):
        datos = self.recv(1024);
        if datos:
            print(datos);
            self.sock[0].send("signal");

class Server(asyncore.dispatcher):

    def __init__(self,host='',port=6666):
        asyncore.dispatcher.__init__(self);
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM);
        self.set_reuse_addr();
        self.bind((host,port));
        self.listen(1);

    def handle_accept(self):
        self.sock,self.addr = self.accept();
        if self.addr:
            print self.addr[0];
        handler = EchoHandler(self.sock);

    def handle_close(self):
        self.close();     

cliente = Server();
asyncore.loop()

此行是一个示例失败,但我想将数据发送到零袜子:

self.sock[0].send("probando");

例如,如果我有5个套接字,请选择发送数据的人

1 个答案:

答案 0 :(得分:5)

说明

你试图从列表中获取袜子并执行其send方法。这会导致错误,因为EchoHandler既没有sock属性也没有套接字列表。正确的方法是获取您想要的EchoHandler实例(基于,例如IP地址,或由某些用户定义的协议分配的插槽),然后使用其发送方法 - 此处(使用dispatcher_with_send)它也比使用发送更好地使用特殊缓冲区。

每次接受连接时都会创建

EchoHandler instantion - 从那时起,它就是一个已建立的通道,用于与给定主机进行通信。 Server侦听任何未建立的连接,而EchoHandler使用socks(由Server中的handle_accept提供)来建立连接,因此EchoHandlerEchoHandler实例作为连接。

解决方案

你需要建立一些连接列表(send() instantions;我们将直接使用缓冲区而不是套接字class Server(asyncore.dispatcher): def __init__(self, host='', port=6666): ... self.connections = [] def handle_accept(self): ... handler = EchoHandler(self.sock, self); self.connections.append(self.sock) ... def remove_channel(self, sock): if sock in self.connections: self.connections.remove(sock) class EchoHandler(asyncore.dispatcher_with_send): def __init__(self, sock, server): ... self.server = server def handle_read(self): datos = self.recv(1024); if datos: print(datos); self.out_buffer += 'I echo you: ' + datos def handle_close(self): self.server.remove_channel(self) self.close() ,并让他们有机会在关闭时删除他们的条目:

EchoHandler

cliente.connections[0].out_buffer += 'I am data'现在知道服务器实例,可以从列表中删除它的套接字。这个echo示例现在功能齐全,使用工作套接字列表,我们可以进行异步发送。

但是,此时您可以根据需要使用此列表 - class ServerThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.daemon = True # if thread is a daemon, it'll be killed when main program exits self.cliente = Server() self.start() def run(self): print 'Starting server thread...' asyncore.loop() thread = ServerThread() while True: msg = raw_input('Enter IP and message divided by semicolon: ') if msg == 'exit': break ip, data = msg.split('; ') for sock in thread.cliente.connections: if sock.addr[0] == ip: sock.out_buffer += data break 将完成工作,但可能您需要更好地控制它。如果是,请继续。

'为谁,由我'

为了异步发送数据,我们需要将asyncore从我们的控制线程中分离出来,我们将在其中输入发送内容和发送给谁。

select()

这将工作并等待目标IP和数据。记得要连接客户端。

正如我所说,你可以使用任何东西来指示哪个套接字是哪个。它可以是具有例如字段的类。 IP和用户名,因此您只能将数据发送给用户名以“D”开头的用户。

可是...

这个解决方案有点粗糙,如果你想要很好地发送数据(这里由于socket的工作方式有一些延迟)需要更好地了解asyncore模块,并充分利用这个def handle_accept(self): self.sock,self.addr = self.accept(); if self.addr: print self.addr[0]; handler = EchoHandler(self.sock); 包装。 Herehere是一些资源。

语法注释

虽然您的代码现在可以使用,但您的代码有一些不太好用的东西。指令末尾的分号不会导致错误,但几乎所有类属性的变量都可以导致它们。例如:

self.sock

self.addrsock.addr[0]可能在该类中用于其他内容(例如,套接字相关的东西;地址),并且覆盖它们可能会造成麻烦。用于请求的方法永远不应保存先前操作的状态。

我希望Python足以让你继续使用它!

修改: sock.socket.getpeername()[0]可以代替self.addr但不需要修改handle_accept(),因此def handle_accept(self): sock, addr = self.accept() if addr: print addr[0] handler = EchoHandler(sock, self) self.connections.append(handler) 应该如下所示:

{{1}}