Отправка данных с использованием уже открытого сокета в python - PullRequest
0 голосов
/ 20 марта 2020

Я создал небольшую программу, которая прослушивает произвольные соединения и обрабатывает их запросы, сохраняя информацию о событиях и соединениях в базе данных sqlite. Как только соединение закрывается и открывается снова, оно обновляет порт источника.

Это работает как чудо, но теперь я хочу иметь возможность произвольно отправлять сообщения этих хостов, и я не могу открыть новые соединения для них, потому что они могут быть позади NAT.

Есть ли способ использовать уже открытые соединения для передачи данных? Я имею в виду, что я мог бы написать функцию в thread_cliente, в то время как True, которая проверяет, есть ли в базе данных сообщение для его доставки, но я решил, что должен быть более простой или более элегантный способ сделать это.

Ниже мой код для сокет-сервера. Я перевел свои комментарии с португальского на английский sh. К сожалению, мои коллеги настаивают на использовании португальских переменных, так что это может вызвать некоторую путаницу.

#!/usr/bin/env python3

import socket
import sys
import logging
from _thread import start_new_thread
from MyPack import all_my_stuff


def print_help():
    print(f'{sys.argv[0]} [TCP Port] [Someting that my program do]')
    sys.exit()


def start_server(porta):
    servico = socket.socket()

    try:
        servico.bind(('', porta))
    except socket.error as e:
        logging.error(e)

    servico.listen(1024) # Is 1024 the max simultaneous client number?

    while True:
        cliente, endereco = servico.accept()
        logging.debug(
            f'New connection {endereco[0]}:{endereco[1]}'
        )
        try:
            start_new_thread(thread_cliente, (cliente, endereco, ))
        except Exception as e:
            logging.error(e)

    servico.close()


def thread_cliente(conexao, endereco):
    while True:
        data = conexao.recv(128)
        if data:
            resposta = None
            sibulla_db.insere_conexao(endereco[0], endereco[1], sys.argv[1])
            resposta = all_my_stuff.do_something(data, sys.argv[1], endereco)
            if resposta:
                logging.debug(f'Sending data: {resposta}')
                conexao.sendall(bytes.fromhex(resposta))
        else:
            #   Close connection
            logging.debug(
                f'Connection closed {endereco[0]}:{endereco[1]}'
            )
            break
    conexao.close()


def main():
    if len(sys.argv) == 1 or sys.argv[1] == 'help':
        #   are you running it right, or asking for help
        print_help()

    #   Log
    logging.basicConfig(
        format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
        filename='sibulla.log',
        level=logging.DEBUG
    )

    #   Start it
    start_server(int(sys.argv[1]))


if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 20 марта 2020

Отправление обратно в исходный сокет, вероятно, является лучшим способом общения с клиентами.

Если вас не беспокоит количество клиентов, слишком большое, вы можете оставить клиентское соединение открытым до нужно и сохраните сокет где-нибудь для дальнейшего использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...