Python клиентский код получает адрес уже используется ошибка - PullRequest
1 голос
/ 17 апреля 2020

У меня есть простой Python HTTP-сервер, который также соединяет другие HTTP-серверы для получения некоторых данных. Хотя при подключении к другим серверам мой сервер выступает в роли http-клиента, но сокет, созданный для входящих запросов на подключение, продолжает прослушивать порт 8080 (у меня есть другой сокет для клиента).

Список других серверы, к которым мне нужно подключиться и получить данные, хранятся в файле JSON, и у меня есть такой код

with open(myjsonfile, 'r') as json_file:
    entries = json.load(json_file)
    for entry in entries.keys():
        address = entries[entry]['address'] 
        port = int(entries[entry]['port'])
        client_port = config.server_port + 50000
        host = gethostname()

        # request the TXT file
        sock = socket(AF_INET,SOCK_STREAM)
        # sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sock.bind((host, client_port))
        sock.connect((address, port))
        reqmsg = "GET /" + config.txt_name + " HTTP/1.0\r\n\r\n"
        sock.sendall(reqmsg.encode())
        response = ''
        response = sock.recv(2048).decode()
        pos = response.find("\r\n\r\n")
        txt_data = response[pos+4:]
        # processing the received data here
        sock.close()

        # request the IMG file
        sock = socket(AF_INET,SOCK_STREAM)
        # sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sock.bind((host, client_port))
        sock.connect((address, port))
        reqmsg = "GET /" + config.img_name + " HTTP/1.0\r\n\r\n"
        sock.sendall(reqmsg.encode())
        response = b''
        while True:
            recvdata = sock.recv(2048)
            if (len(recvdata) < 1): 
                break
            response = response + recvdata
        pos = response.find(b"\r\n\r\n")
        img_data = response[pos+4:]
        # working with the image here
        sock.close()

Я должен использовать заданный номер порта для своего клиента, потому что именно так сервер определяет меня. Однако иногда я получаю сообщение об ошибке «Адрес уже используется» для второго вызова socket.bind() (тот, что для изображения). Без звонков bind() мой код работает нормально. Я попытался установить параметры сокета (закомментировано в приведенном выше коде) и использовать pycurl со свойством LOCALPORT, для которого установлено значение client_port выше, но все равно получал ту же ошибку.

В чем может быть причина сообщение об ошибке? Я думаю, что я открываю и закрываю сокеты, так что операционная система должна освободить порт для дальнейшего использования (я думаю)?

Спасибо

PS: Это небольшой проект, а не производственная система, поэтому не беспокойтесь о том, «зачем использовать номера портов для идентификации клиентов»

1 Ответ

0 голосов
/ 17 апреля 2020

После завершения сеанса существует TIME_WAIT, чтобы убедиться, что в сети по-прежнему нет живых пакетов. Когда вы воссоздаете тот же кортеж, и один из этих пакетов появляется, он будет рассматриваться как действительный пакет для вашего соединения это вызовет состояние ошибки. Обычно максимальный возраст 2xpacket, прежде чем пакет будет отброшен

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

Попробуйте использовать;

...
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.listen([backlog])
sock.bind((host, client_port))
...

socket.listen ([backlog])

...