Python httpd будет прослушивать используемые порты, не выдавая ошибку сокета в Windows, но не OS X? - PullRequest
1 голос
/ 07 января 2012

Это действительно продолжение моего поста о Python oauth2 BaseHTTPServer, конфликтующего с SABNzbd +.

По сути, у меня есть следующий маленький скрипт (который используется для создания локального сервера, прослушивающего учетные данные Google API oauth2):

import socket
import BaseHTTPServer
from oauth2client.tools import ClientRedirectServer, ClientRedirectHandler

port_number = 0
host_name = 'localhost'
for port_number in range(8080,10000):
    try:
        httpd = ClientRedirectServer((host_name, port_number),
                                   ClientRedirectHandler)
    except socket.error, e:
        print "socket error: " + str(e)
        pass
    else:
        print "The server is running on: port " + str(port_number)
        print "and host_name " + host_name
        httpd.serve_forever()
        break

В OS X, если я дважды запускаю этот скрипт, я получаю ожидаемые результаты:

socket error: [Errno 48] Address already in use
The server is running on: port 8081
and host_name localhost

Однако, запустив один и тот же сценарий из разных окон cmd в Win7, я могу без проблем запустить 3 или 4 сервера на одном и том же порту (8080), не выдавая ошибку сокета:

C:\>netstat -abn | Findstr 8080
TCP    127.0.0.1:8080    0.0.0.0:0    LISTENING
TCP    127.0.0.1:8080    0.0.0.0:0    LISTENING

Ответы [ 3 ]

1 голос
/ 07 января 2012

Очевидно, что Windows отличается от большинства систем Unix-y семантикой в ​​отношении привязки нескольких сокетов к одному и тому же адресу / порту. См., Например, этот выпуск Python среди других.

0 голосов
/ 08 января 2012

В комментариях Неда Дейли Windows не обрабатывает несколько сокетов так же, как другие ОС.

Я думаю, что правильный способ сделать это в Windows (и способ, который работал для меня, и, следовательно, ответ, который я выберу), - это привязать порт к 0 и позволить Windows обрабатывать его самостоятельно. Затем вы можете вернуть номер используемого порта с помощью sock.getsockname()[1].

Для всех, кто пытается сделать это с помощью Google oauth2client.tools, см. Код, который я использовал ниже:

import socket
import BaseHTTPServer
from oauth2client.tools import ClientRedirectServer, ClientRedirectHandler

port_number = 0
host_name = 'localhost'
try:
    httpd = ClientRedirectServer((host_name, port_number), ClientRedirectHandler)
except socket.error, e:
    print "socket error: " + str(e)
else:
    print "The server is running on: port " + str(httpd.socket.getsockname()[1])
    print "and host_name " + host_name
    httpd.serve_forever()
0 голосов
/ 07 января 2012

Вы не должны иметь возможность подключать несколько приложений к одной конечной точке.

...