Advertisement
noctual

Chat Server

Apr 11th, 2021
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.01 KB | None | 0 0
  1. import asyncio, socket, hashlib, datetime, struct, json
  2.  
  3. LISTEN_PORT = 1111
  4. COUNT_MAX_PEER = 5
  5.  
  6. class Peer(object):
  7.     def __init__(self, server, sock, name):
  8.         self.loop = server.loop
  9.         self.name = name
  10.         self._sock = sock
  11.         self._server = server
  12.         self.loop.create_task(self._peer_handler())
  13.  
  14.     def send(self, data):
  15.         return self.loop.sock_sendall(self._sock, data)
  16.  
  17.     async def sendFile(self, filename):
  18.         with open(filename, 'rb') as f:
  19.             return await self.loop.sock_sendfile(self._sock, f)
  20.    
  21.     async def _peer_handler(self):
  22.         try:
  23.             await self._peer_loop()
  24.         except IOError:
  25.             pass
  26.         finally:
  27.             await self._server.remove(self)
  28.  
  29.     async def _peer_loop(self):
  30.         while True:
  31.             request = await self.loop.sock_recv(self._sock, 1024)
  32.             print (request)
  33.             indexEndHead = request.find(b'\r\n\r\n')
  34.             if indexEndHead != -1:
  35.                 head = request[:indexEndHead].splitlines()
  36.                 heads = {title[0]: title[1] for title in [line.split(b':', 1) for line in head[1:]]}
  37.                 data = request[indexEndHead+4:]
  38.                 date = datetime.datetime.today().timestamp()
  39.  
  40.                 if head[0] == b'MESSANGE':
  41.                     await self._server.sendAllPeers({'data': {'type': 'mess', 'text': data.decode('utf-8'), 'name': self.name, "date": date}, 'peer': self})
  42.                 elif head[0] == b'NICKNAME':
  43.                     newname = data.decode('utf-8')
  44.                     await self._server.sendAllPeers({'data': {'type': 'system', 'text': f"user '{self.name}' changed name to '{newname}'", "date": date}, 'peer': self})
  45.                     self.name = newname
  46.                 elif head[0] == b'FILE':
  47.                     tempFileName = hashlib.sha1(struct.pack('f', datetime.datetime.today().timestamp())).hexdigest()
  48.                     with open(tempFileName, 'wb') as f:
  49.                         numBytes = len(data)
  50.                         f.write(data)
  51.                         while numBytes < int(heads[b'Content-Length']):
  52.                             data = await self.loop.sock_recv(self._sock, 1024)
  53.                             numBytes += len(data)
  54.                             f.write(data)
  55.                     await self._server.sendAllPeers({'data': {'type': 'file', 'name': self.name, 'date': date, 'len': numBytes, 'filename': heads[b'File-name'].decode('utf-8')}, 'temppath': tempFileName, 'peer': self})    
  56.  
  57. class ChatServer(object):
  58.     def __init__(self, loop, port, max_peer):
  59.         self.loop = loop
  60.         self._serv_sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
  61.         self._serv_sock.setblocking(0)
  62.         self._serv_sock.bind(('', port))
  63.         self._serv_sock.listen(max_peer)
  64.         self._peers = []
  65.         self.loop.create_task(self._server())
  66.  
  67.     async def remove(self, peer):
  68.         self._peers.remove(peer)
  69.         await self.sendAllPeers({'data': {'type': 'system', 'text': 'user %s quit!' % (peer.name,), 'date': datetime.datetime.today().timestamp()}})
  70.  
  71.     async def sendAllPeers(self, data):
  72.         message = json.dumps(data['data']).encode('utf8')
  73.         for peer in self._peers:
  74.             await peer.send(f"OK\r\nContent-Length:{len(message)}\r\n\r\n".encode('utf-8') + message)
  75.             if data['data']['type'] == 'file':
  76.                 await peer.sendFile(data['temppath'])
  77.  
  78.     async def _server(self):
  79.         while True:
  80.             peer_sock, peer_name = await self.loop.sock_accept(self._serv_sock)
  81.             peer_sock.setblocking(0)
  82.             peer = Peer(self, peer_sock, str(peer_name))
  83.             self._peers.append(peer)
  84.             await self.sendAllPeers({'data': {'type': 'system', 'text': 'user %s connected!' % (peer.name,), 'date': datetime.datetime.today().timestamp()}})
  85.  
  86. def main():
  87.     loop = asyncio.get_event_loop()
  88.     ChatServer(loop, LISTEN_PORT, COUNT_MAX_PEER)
  89.     loop.run_forever()
  90.  
  91. if __name__ == '__main__':
  92.     main()
  93.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement