Fra*_*sco 0 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()
Run Code Online (Sandbox Code Playgroud)
这一行是一个例子失败,但我想将数据发送到零袜子:
self.sock[0].send("probando");
Run Code Online (Sandbox Code Playgroud)
例如,如果我有5个套接字,请选择发送数据的人
你试图从列表中获取袜子并执行其send方法.这会导致错误,因为EchoHandler
既没有sock属性也没有套接字列表.正确的方法是获取EchoHandler
您想要的实例(基于,例如IP地址,或由某些用户定义的协议分配的插槽),然后使用其发送方法 - 这里(带dispatcher_with_send
)它也更好地使用特殊缓冲区发送.
EchoHandler
每次接受连接时都会创建instantion - 从那时起它就是与给定主机通信的已建立通道.Server
侦听任何未建立的连接,同时EchoHandler
使用socks(由Server
in 给出handle_accept
)用于已建立的连接,因此存在EchoHandler
与连接一样多的实例.
你需要建立一些连接列表(EchoHandler
实例;我们将使用缓冲区,而不是套接字send()
直接),并让他们有机会在关闭时删除他们的条目:
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()
Run Code Online (Sandbox Code Playgroud)
EchoHandler
现在知道服务器实例,可以从列表中删除它的套接字.这个echo示例现在功能齐全,使用工作套接字列表,我们可以继续进行异步发送.
但是,此时您可以根据需要使用此列表 - cliente.connections[0].out_buffer += 'I am data'
将完成工作,但可能您需要更好地控制它.如果是,请继续.
为了异步发送数据,我们需要将asyncore从我们的控制线程中分离出来,我们将在其中输入要发送的内容和向谁发送.
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
Run Code Online (Sandbox Code Playgroud)
这将工作并等待目标IP和数据.记得要连接客户端.
正如我所说,你可以使用任何东西来指示哪个套接字是哪个.它可以是具有例如字段的类.IP和用户名,因此您只能将数据发送给用户名以"D"开头的用户.
这个解决方案有点粗糙,如果你想要很好地发送数据(这里由于select()
工作方式有一些延迟)并且充分利用这个socket
包装器,需要更好地了解asyncore模块.
这里和这里有一些资源.
虽然您的代码现在可以正常工作,但您的代码有一些不太好的东西.指令末尾的分号不会导致错误,但几乎所有类属性的变量都可以导致它们.例如这里:
def handle_accept(self):
self.sock,self.addr = self.accept();
if self.addr:
print self.addr[0];
handler = EchoHandler(self.sock);
Run Code Online (Sandbox Code Playgroud)
self.sock
并且self.addr
可能在该类中用于其他东西(例如,与套接字相关的东西;地址)并覆盖它们可能会造成麻烦.用于请求的方法永远不应保存先前操作的状态.
我希望Python足以让你继续使用它!
编辑: sock.addr[0]
可以代替使用,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)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2023 次 |
最近记录: |