1

そのため、割り当てにUDPを使用して基本的な「ping」アプリケーションを作成しています.socket.settimeout()の実装を除いてすべてが機能しています。理由はわかりませんが、バインドされたソケットに関係しています。Python の癖かもしれませんが、文書化する前に確認したいと思います。私は機能的なコードの答えを探しているのではなく (それは不正行為です)、むしろ私が持っているものが壊れている理由を探しています. (例:Pythonが同じマシン上のクライアント/サーバーを好まないという文書化されていない理由など)

Python ソケット タイムアウトの詳細: http://docs.python.org/2/library/socket.html#socket.socket.settimeout

以下に示すコードでは、同じマシンで実行されているサーバーとの通信は成功していますが、クライアントがソケットにバインドされていない場合のみです。しかし、ソケットにバインドされていない場合、タイムアウト システムは失敗します (これはサーバーの電源を切ることによってテストされており、10 個のタイムアウトすべてがすぐに一度に出力されます)。

注: コードは理想的ではありませんが、これはネットワーク理論のクラスであり、プログラミングのクラスではありません。最終的には機能するだけです。今すぐ提出してAを取得できますが、タイムアウト機能が機能しない理由を理解したいです。

編集:問題を明確にするために、クライアントでの Bind の使用は、UDP がそれを必要としないことに気付く前に、サーバー コードがそれを持っているのを見た後でしたが、たまたまタイムアウト機能を適切に機能させましたが、通常の操作を中断しました。socket.settimeout() 宣言はおそらく TCP でしか機能しませんか?

クライアント コード (タイムアウトあり):

import socket
import time
import select


data = "Re-verify our range to target... one ping only. \n"

addrDest = ("127.0.0.1",8675)
addrLocal = ("127.0.0.1",12345)

totalTime = 0
averageTime = 0
totalPings = 0
#timeout_seconds = 1.0

UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
UDPSock.bind(addrLocal) 
# adding bind here even though it's UDP makes timeout work,
# but breaks normal functionality
UDPSock.settimeout(1)


while (totalPings < 10):
 totalPings = (totalPings + 1)
 start = time.clock()
 str_list = []
 str_list.append(str(totalPings))
 str_list.append(" ")
 str_list.append(str(start))
 str_list.append(" ")
 str_list.append(data)
 dataOut = ''.join(str_list)
 UDPSock.sendto(dataOut,addrDest)
 try:
      dataIn,addrIn = UDPSock.recvfrom(1024)
      print dataIn.strip(),"\n",addrIn
      elapsed = ((time.clock() - start) * 1000)
      print elapsed, " ms round trip"
 except socket.error:
      print "Connection timed out for Packet #", totalPings

サーバーコード:

import socket

UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

# (to all IP addresses on this system)
listen_addr = ("",8675)
UDPSock.bind(listen_addr)

# Report on all data packets received and
# where they came from in each case (as this is
# UDP, each may be from a different source and it's
# up to the server to sort this out!)
while True:
    data,addr = UDPSock.recvfrom(1024)
    print data.strip(),addr
    UDPSock.sendto(data,addr)
4

2 に答える 2

2

クライアントのローカル アドレスにバインドする必要があるのはなぜですか? クライアントはいつでもサーバーとしても機能しますか? そうでない場合、クライアントをバインドする必要はまったくありません。クライアントがサーバーとして機能する必要がある場合にのみ、特定のポートが必要です。bind を呼び出さない場合は、1024 - 65535 (私の記憶が正しければ) およびこれは UDP パケットの送信元ポートになります。送信元アドレスは、クライアントが実行されるアドレスです。

バークレーソケットによると

bind() assigns a socket to an address. When a socket is created using socket(), 
it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts

これが Networking クラスのプロジェクトであり、Client-Server アーキテクチャを実装しようとしている場合は、クライアント コード内からbindを呼び出さないでください。これは、Client が Server として機能することはなく、Client が Client に接続する Server ではなく、Listening Server に接続する必要があるためです。

アップデート:

Bind は TCP クライアント サーバー設計から呼び出す必要がある場合がありますが、UDP クライアント サーバー モデルからではなく、UDP は送信して忘れる設計であり、低レベルのパケット送信成功確認がないためです。UDP パケットには、それ自体に送信元アドレスとポートがあります。

于 2013-02-20T06:57:04.767 に答える