带有线程和多客户端的Python聊天服务器

时间:2016-06-15 23:46:17

标签: python sockets

我的目标是获取一个提供的框架python文件并添加功能以创建一个处理多个客户端的聊天服务器。我已经在chat_output,服务器和客户端函数中进行了编辑。

第一步是让客户端连接没有问题。 然后我需要添加一个raw_input()调用,以便用户可以键入内容,将其发送到服务器,然后将服务器sendall()发送给客户端。

import socket
import time

def timestamp():
    result = int(time.time())
    return result


class Stream(object):
    " abstract "
    def write(self,data):
        pass
    def read(self):
        pass

class TCPStream(Stream):
    def __init__(self,the_socket):
        self.s = the_socket
        self.address = None
    def read(self,amount=None):
        if amount is None:
            return self.s.recv(4096)
        else:
            return self.s.recv(amount)
    def set_address(self,address):
        self.address = address
    def get_address(self):
        return self.address
    def write(self,data):
        self.s.sendall(data)
    def __del__(self):
        self.s.close()
    def shutdown(self):
        self.s.shutdown(socket.SHUT_WR)

class Socket(object):
    pass

class TCPBaseSocket(Socket):
    def __init__(self,port):
        self.s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.port = port

class TCPReceivingSocket(TCPBaseSocket):
    def __init__(self,port,address=''):
        super().__init__(port)
        self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.s.bind((address,self.port))
        self.s.listen(1)
    def connection(self):
        sc, sockname = self.s.accept()
        result = TCPStream(sc)
        result.set_address(sockname)
        return result

class TCPSendingSocket(TCPBaseSocket):
    def __init__(self,port,address):
        super().__init__(port)
        self.s.connect((address,port))
        self._stream = TCPStream(self.s)
        self._stream.set_address((address,port))
    def stream(self):
        return self._stream

if __name__ == "__main__":
    import argparse
    import threading
    import sys

    def chat_input(stream):
        """
            Enter your code here, shouldn't need to be more than 10 lines of code
        """

        pass

    def chat_output(stream):        
        """
        Enter your code here, shouldn't need to be more than 10 lines of code
        """

        #stream = TCPStream(stream)
        s = TCPStream(stream)
        while True:
            data = s.read()    #s.recv(4096)
            if not data:
                print("Disconnected from chat server")
                break
            #stream.write(data)      #sendall(data)



    def server(interface,port):
        """
        Enter your code here, shouldn't need to be more than 10 lines of code
        """

        tsc = TCPReceivingSocket(port, interface)
        print("Server is running.....\n")

        addr = tsc.connection().get_address()
        print(addr, " is now connected!\n")


        server_input_thread = threading.Thread(target = chat_input, args = (tsc,))
        server_output_thread = threading.Thread(target = chat_output, args = (tsc,))

        server_input_thread.start()
        server_output_thread.start()
        server_input_thread.join()
        server_output_thread.join()

    def client(interface,port):
        """
        Enter your code here, shouldn't need to be more than 10 lines of code
        """
        tsc = TCPSendingSocket(port, interface)


        client_input_thread = threading.Thread(target = chat_input, args=(tsc,))
        client_output_thread = threading.Thread(target = chat_output, args=(tsc,))

        client_input_thread.start()
        client_output_thread.start()
        client_input_thread.join()
        client_output_thread.join()

    choices = {'client':client,'server':server}
    parser = argparse.ArgumentParser(description='Chat via TCP')
    parser.add_argument('role',choices=choices,help="which role to take")
    parser.add_argument('host',help='interface the server listens at; host the client sends to')
    parser.add_argument('-p',metavar='PORT',type=int,default=1060,help='TCP port (default 1060)')
    args = parser.parse_args()
    function=choices[args.role]
    function(args.host,args.p)

对于正在运行此操作的人,请使用命令行:

  

python3 [filename] .py server localhost

     

python3 [filename] .py client localhost

当我跑步时: 服务器连接。现在我如何使用TCPStream对象?该参数应该传递给'stream'对象,但它是一个TCPR / Ssocket

服务器:

E:\School\CSIS\440\Assignment7>py talk.py server localhost
Server is running.....

('127.0.0.1', 53829)  is now connected!

Exception in thread Thread-2:
Traceback (most recent call last):
  File "E:\School\Python\lib\threading.py", line 914, in _bootstrap_inner
    self.run()
  File "E:\School\Python\lib\threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "talk.py", line 85, in chat_output
    data = s.read()    #s.recv(4096)
  File "talk.py", line 22, in read
    return self.s.recv(4096)
AttributeError: 'TCPReceivingSocket' object has no attribute 'recv'

Exception ignored in: <bound method TCPStream.__del__ of <__main__.TCPStream obj
ect at 0x010B68B0>>
Traceback (most recent call last):
  File "talk.py", line 32, in __del__
    self.s.close()
AttributeError: 'TCPReceivingSocket' object has no attribute 'close'

E:\School\CSIS\440\Assignment7>

客户端:

E:\School\CSIS\440\Assignment7>py talk.py client localhost
Exception in thread Thread-2:
Traceback (most recent call last):
  File "E:\School\Python\lib\threading.py", line 914, in _bootstrap_inner
    self.run()
  File "E:\School\Python\lib\threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "talk.py", line 85, in chat_output
    data = s.read()    #s.recv(4096)
  File "talk.py", line 22, in read
    return self.s.recv(4096)
AttributeError: 'TCPSendingSocket' object has no attribute 'recv'

Exception ignored in: <bound method TCPStream.__del__ of <__main__.TCPStream obj
ect at 0x00C068F0>>
Traceback (most recent call last):
  File "talk.py", line 32, in __del__
    self.s.close()
AttributeError: 'TCPSendingSocket' object has no attribute 'close'

E:\School\CSIS\440\Assignment7>

0 个答案:

没有答案