繁体   English   中英

如何从聊天服务器与多个客户端聊天

[英]How to chat with multiple clients from a chat server

问题:

  • 如何通过OS控制台中的聊天服务器与任何用户客户端聊天?
  • 有人可以帮我为多个客户建立工作机制吗? 作业机制由os终端控制台控制。

与服务器聊天

启动聊天服务器,并从客户端建立聊天连接。

$ nc -v 127.0.0.1 4444 

双重客户如下:

 ====================     |---->  [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

当有多个客户端可用时,聊天服务器的控制台将发送“ Hello World”,并显示

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])

具有多客户端的ChatServer


聊天服务器代码

#!/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()

这个self.set_reuse_addr()通常不是一个好主意,但是对于开发来说是很好的。 尝试改为正确关闭连接。

我认为问题是您最终从ConsoleHandler调用了handle_read()两次(也许在其中放了一个print("CH read")来检查代码的逻辑)。 要发送数据,请添加对handle_write的调用。

 def handle_read(self):
    self.current_chat.out_buffer += self.recv(self.BUFSIZE)
    self.current_chat.handle_write()

我将sent = self.send(self.out_buffer)更改为sent = self.send(bytes(self.out_buffer, encoding="utf-8"))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM