Advertisement
pegorino

echo_server

Jan 10th, 2018
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.87 KB | None | 0 0
  1. # -------- Эхо-сервер, обрабатывающий "одновременно" несколько клиентов -------
  2. #              Обработка клиентов осуществляется функцией select
  3.  
  4. import select
  5. import json
  6. from socket import socket, AF_INET, SOCK_STREAM
  7.  
  8.  
  9. def parse(data):
  10.     """
  11.    преобразует данные из байт-строки json в словарь,
  12.    либо из словаря в байт-строку json
  13.    использовать при каждой отправке/приеме данных
  14.    :param data:
  15.    :return:
  16.    """
  17.     if type(data) is bytes:
  18.         return json.loads(data.decode('utf-8'))
  19.     else:
  20.         return json.dumps(data).encode('utf-8')
  21.  
  22.  
  23. def read_requests(r_clients, all_clients):
  24.     ''' Чтение запросов из списка клиентов
  25.    '''
  26.     responses = {}      # Словарь ответов сервера вида {сокет: запрос}
  27.  
  28.     for sock in r_clients:
  29.         try:
  30.  
  31.             bdata = sock.recv(1024)
  32.             data = parse(bdata)
  33.             responses[sock] = data
  34.             print('r --> ', [(c.fileno(), c.getpeername()[1]) for c in r_clients])
  35.             print('\n', 'клиент {} пишет в {}'.format(data['from'], data['to']), end=': ')
  36.  
  37.         except:
  38.             print('Клиент r {} {} отключился'.format(sock.fileno(), sock.getpeername()))
  39.             all_clients.remove(sock)
  40.  
  41.     return responses      
  42.  
  43.  
  44. def write_responses(requests, w_clients, all_clients):
  45.     ''' Эхо-ответ сервера клиентам, от которых были запросы
  46.    '''
  47.  
  48.     for sock in w_clients:
  49.         if sock in requests:
  50.             try:
  51.  
  52.                 # Подготовить и отправить ответ сервера
  53.                 message = {'message from': requests[sock]['from'], 'text': requests[sock]['message']}
  54.                 print(message)
  55.                 bmessage = parse(message)
  56.  
  57.                 sock.send(bmessage)
  58.                 print('w --> ', [(c.fileno(), c.getpeername()[1]) for c in w_clients])
  59.                 print('requests --> ', {requests})
  60.  
  61.             except:                 # Сокет недоступен, клиент отключился
  62.                 print('Клиент w {} {} отключился'.format(sock.fileno(), sock.getpeername()))
  63.                 sock.close()
  64.                 all_clients.remove(sock)
  65.  
  66.  
  67. def mainloop():
  68.     ''' Основной цикл обработки запросов клиентов
  69.    '''
  70.     address = ('', 7777)
  71.     clients = []
  72.  
  73.     s = socket(AF_INET, SOCK_STREAM)
  74.     s.bind(address)
  75.     s.listen(5)
  76.     s.settimeout(0.2)   # Таймаут для операций с сокетом
  77.     while True:
  78.         try:
  79.             conn, addr = s.accept()  # Проверка подключений
  80.         except OSError as e:
  81.             pass                     # timeout вышел
  82.         else:
  83.             print("Получен запрос на соединение от {}".format(addr[1]))
  84.             clients.append(conn)            
  85.         finally:                    
  86.             # Проверить наличие событий ввода-вывода
  87.             wait = 0
  88.             r = []
  89.             w = []
  90.             try:
  91.                 r, w, e = select.select(clients, clients, [], wait)
  92.  
  93.             except:
  94.                 pass            # Ничего не делать, если какой-то клиент отключился    
  95.  
  96.             requests = read_requests(r, clients)      # Сохраним запросы клиентов
  97.  
  98.             write_responses(requests, w, clients)     # Выполним отправку ответов клиентам                  
  99.  
  100.  
  101. print('Эхо-сервер запущен!')
  102. mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement