6

私は自分の python サーバーで遊んでいますが、localhost の使用は終わったので、インターネットに接続したいと考えています。これまでの私のコードは次のとおりです。

import socket
import threading
import socketserver

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

    def handle(self):
        data = self.request.recv(1024)
        cur_thread = threading.current_thread()
        response = "{}: {}".format(cur_thread.name, data)
        self.request.sendall(b'worked') 

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

def client(ip, port, message):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((ip, port))
    try:
        sock.sendall(message)
        response = sock.recv(1024)
        print("Received: {}".format(response))
    finally:
        sock.close()

if __name__ == "__main__":
    # Port 0 means to select an arbitrary unused port
    HOST, PORT = "0.0.0.0", 9001

    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address

    # Start a thread with the server -- that thread will then start one
    # more thread for each request
    server_thread = threading.Thread(target=server.serve_forever)
    # Exit the server thread when the main thread terminates
    server_thread.daemon = True
    server_thread.start()
    print("Server loop running in thread:", server_thread.name)
    ip = '12.34.56.789' #Not my real ip address This is just to hide my ip
    print(ip, PORT)

    client(ip, PORT, b'Hello World 1')
    #client(ip, port, b'Hello World 2')
    #client(ip, port, b'Hello World 3')

    server.shutdown()

これを実行すると、次のエラーが表示されます。

Server loop running in thread: Thread-1
12.34.56.789 9001
Traceback (most recent call last):
  File "C:/Python32/serverTesty.py", line 43, in <module>
    client(ip, PORT, b'Hello World 1')
  File "C:/Python32/serverTesty.py", line 18, in client
    sock.connect((ip, port))
socket.error: [Errno 10061] No connection could be made because the target machine actively refused it

プログラムの実行中にポート 9001 で canyouseeme.org を使用すると、アクティブで動作していると表示されるため、ポートが機能していることはわかっています。だから、どこかで接続が間違っているだけだと思います。

4

1 に答える 1

27

ip = '12.34.56.789' #私の本当の IP アドレスではなく、whatismyip.org から取得したものです

最初の問題は、「12.34.56.789」が有効な IP アドレスではないことです。各コンポーネントは 8 ビット (0 ~ 255) に収まる必要があります。789はありえない。しかし、出力が 12.45.29.122 を示しているため、これは実際に実行しているコードではないと思います。

2 つ目の問題は、実際の住所ではない住所を使用していることです。

お使いのマシンにはおそらく、LAN からのみアクセスできる内部 IP アドレスがあります。次に、ルーターに外部 IP アドレスがあります。ルーターは、ネットワーク アドレス変換と呼ばれる手法を使用して、LAN 上の各マシンがクライアントとして動作しているときに、外部アドレスが自分に属しているように装わせます (これが、whatismyip.org がそのアドレスを表示する理由です)。しかし、それらがサーバーとして機能している場合、それは機能しません。

考えてみれば、本当にうまくいくはずがありません。アウトバウンド接続を確立し、誰かが応答した場合、ルーターは応答があなたのマシンに送られるべきであることを認識します。しかし、誰かがやってきて突然ルーターに話しかけた場合、どのマシンに接続を送るべきかをどのように知ることができるでしょうか?

同じ LAN 内から接続しようとしている場合、非常に簡単な解決策があります。ルーターの外部アドレスではなく、サーバーの実際の内部アドレスを使用します。

外部から接続する必要がある場合は、追加の作業がなければ接続できません。これを回避するには、次の 4 つの方法があります。

  1. あなたのマシンに実際にパブリックにアドレス可能な IP アドレスを与えてください (例えば、ルーターの DMZ に置くことによって)。これは通常、ホーム ユーザーにとっては選択肢でさえありません。また、自分が何をしているのかを知らない人にとっては、悪い選択肢です (ランチタイムまでに自分のマシンを誰かのボットネットの一部にしたい場合を除きます)。

  2. ルーターの構成で静的ポート転送を設定します。これはルーターごとに異なりますが、「誰かがポート 9001 を探しに来た場合は、常にマシン 192.168.1.64 に送信してください」と伝えるという考え方です。

  3. UPnP を使用して、ポート フォワーディングを動的に設定します。

  4. NAT ホール パンチングをセットアップします。

オプション 3 と 4 はより複雑で、オプション 2 が必要なオプションだと思いますので、説明しません。

それに加えて:

HOST, PORT = "192.168.1.64", 9001

server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

サーバーに明示的に「192.168.1.64をリッスンする」ように指示しました。サーバー マシンを DMZ に配置してアドレス 192.168.1.64 と 12.45.29.122 を設定したとしても、プログラムは最初の接続のみをリッスンするため、2 番目の接続を使用して到達することはできません。すべてのアドレスでリッスンする場合は、0.0.0.0 を使用します。

編集されたバージョンでは、0.0.0.0 でリッスンし、ルーターのパブリック IP に接続し、ルーターでポート転送を設定したと主張していますが、まったく同じエラーが引き続き発生します。

それがすべて正しければ、明らかに間違っている可能性があることが 3 つあります。

  1. 実際にはポート転送ではありません。セットアップに何か問題があります。
  2. 実際には 0.0.0.0:9001 をリッスンしていません。
  3. ファイアウォールが接続をブロックしています。

物事を絞り込むためにできるいくつかのテストがあります。

  1. 2 つのターミナルを開きます。1 つに、タイプしnc -kl 9001ます。もう一方には、 と入力しnc 12.34.56.78 9001ます。それらは接続されているはずなので、一方のウィンドウに入力したものはもう一方のウィンドウに表示されます (Return キーを押した後でのみ可能かもしれません)。それが機能する場合、ポート転送は機能しており、ファイアウォールの問題はないため、コードに問題があります。

  2. それでもうまくいかない場合は、各ウィンドウで見たものを正確に投稿してください。次に Ctrl-C を 2 番目に入力ncし、 と入力しnc 192.168.1.64 9001ます。これで問題が解決した場合は、同じホスト (または同じインターフェイス) 接続を許可するがリモート接続を許可しない巧妙なファイアウォールがない限り、ポート転送が正しく設定されていないかのどちらかです。

  3. どちらも機能しない場合は、おそらくファイアウォールの問題です。(IP アドレスなどに誤りがない限り。) おそらくどこかにログを見つけることができますが、使用しているプラ​​ットフォームや使用しているファイアウォールを知らなければ、多くの助けを提供することは困難です。(また、これはおそらく SO とは異なるサイトの問題です。)

Windows または一部の Linux ディストリビューションを使用している場合は、ncどこかから (netcat) のコピーを取得する必要があります。ほとんどの Linux ディストリビューションと Mac では、組み込まれている必要があります。また、GNU、BSD、および Hobbitncはわずかに異なるためnc -kl 6000、エラーが発生した場合は、man ページまたは--help. (私の記憶が正しければ、Hobbitncでは が必要であり-l -p6000、BSD では が必要であり-l 6000、GNU ではどちらでも使用できます。)

または、上で使用した構文を処理できることがわかっている netcat の再実装であるncatが必要な場合があり、Windows 用の単一ファイルの静的実行可能ファイルがあります。

を使い始められない場合はnc、少なくとも 12.34.56.78 ではなく 192.168.1.64 に接続するようにコードを変更してみてください。これで問題が解決した場合、少なくとも、それがポート フォワーディングか、同じホスト/インターフェイス接続を許可するがリモート接続を許可しないファイアウォールであることがわかります。

于 2012-09-28T00:23:24.337 に答える