Reputation: 1079
The issues:
Start a chat server, and make chat connections from clients.
$ nc -v 127.0.0.1 4444
Double clients as follow:
==================== |----> [client1: ('127.0.0.1', 37748)]
| Server (Console) |<----|
==================== |----> [client2: ('127.0.0.1', 37750)]
root@lab:/tmp# python ChatManager.py
start a chat server: ('127.0.0.1', 4444)
[+] client: ('127.0.0.1', 37748)
[+] client: ('127.0.0.1', 37750)
Hello World
When multiple clients are available, the console of chat server sends "Hello World", and it shows
error: uncaptured python exception, closing channel <__main__.ConsoleHandler connected at 0xb73e96ec>
(<type 'exceptions.OSError'>:
[Errno 11] Resource temporarily unavailable
[/usr/lib/python2.7/asyncore.py|read|83]
[/usr/lib/python2.7/asyncore.py|handle_read_event|449]
[ChatManager.py|handle_read|17] [/usr/lib/python2.7/asyncore.py|recv|387]
[/usr/lib/python2.7/asyncore.py|recv|619])
#!/usr/bin/env python
# -*- coding: utf8 -*-
import asyncore
import sys
class ConsoleHandler(asyncore.file_dispatcher):
"""Enable console interactive for socket read/write.
"""
def __init__(self, sender, file):
asyncore.file_dispatcher.__init__(self, file)
self.current_chat = sender
self.BUFSIZE = 1024
def handle_read(self):
self.current_chat.out_buffer += self.recv(self.BUFSIZE)
class ChatManager(asyncore.dispatcher):
"""Handle tcp in-connections, ex: send commands to targets.
"""
def __init__(self, _sock=None, _map=None):
asyncore.dispatcher.__init__(self, _sock, _map)
self.out_buffer = ''
self.BUFSIZE = 1024
def handle_read(self):
data = self.recv(self.BUFSIZE)
print(data.strip())
# self.send(data)
def handle_write(self):
if self.out_buffer != "":
sent = self.send(self.out_buffer)
self.out_buffer = self.out_buffer[sent:]
def handle_error(self):
pass
def handle_close(self):
"""Called when the socket is closed.
"""
self.close()
class Listener(asyncore.dispatcher):
"""Start a tcp listener (default: 127.0.0.1:4444), and wait for connections.
If a new connection, `ChatManager' will try to handle it.
"""
def __init__(self, addr=('127.0.0.1', 4444), max_connections=4):
asyncore.dispatcher.__init__(self)
self.connections = []
self.create_socket(asyncore.socket.AF_INET, asyncore.socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(addr)
self.listen(max_connections)
print('start a chat server: {}'.format(addr))
def handle_accept(self):
client, caddr = self.accept()
print('[+] client: {}'.format(caddr))
ConsoleHandler(ChatManager(client), sys.stdin)
if __name__ == "__main__":
Listener()
asyncore.loop()
Upvotes: 0
Views: 665
Reputation: 327
This self.set_reuse_addr()
is generally a bad idea, but fine for development. Try to properly close your connections instead.
I think the problem is you end up calling handle_read()
from ConsoleHandler twice (perhaps put a print("CH read")
in there to check the logic of your code).
To send data, add a call to handle_write.
def handle_read(self):
self.current_chat.out_buffer += self.recv(self.BUFSIZE)
self.current_chat.handle_write()
I changed sent = self.send(self.out_buffer)
to sent = self.send(bytes(self.out_buffer, encoding="utf-8"))
Upvotes: 0