pythonに非常に基本的なサーバーを作成しようとしています。このサーバーは、ポートでリッスンし、クライアントが接続を試み、データを受信し、何かを送信してから再度リッスンするときにTCP接続を作成します(そしてプロセスを無期限に繰り返します)。これは私がこれまでに持っているものです:
from socket import *
serverName = "localhost"
serverPort = 4444
BUFFER_SIZE = 1024
s = socket(AF_INET, SOCK_STREAM)
s.bind((serverName, serverPort))
s.listen(1)
print "Server is ready to receive data..."
while 1:
newConnection, client = s.accept()
msg = newConnection.recv(BUFFER_SIZE)
print msg
newConnection.send("hello world")
newConnection.close()
時々これは完全にうまくいくようです(ブラウザで「localhost:4444」を指定すると、サーバーはHTTP GETリクエストを出力し、ウェブページは「hello world」というテキストを出力します)。しかし、最後の数分でサーバーを閉じた後にサーバーを起動しようとすると、散発的に次のエラーメッセージが表示されます。
Traceback (most recent call last):
File "path\server.py", line 8, in <module>
s.bind((serverName, serverPort))
File "C:\Python27\lib\socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Windows 7を使用してpythonでプログラミングしています。これを修正する方法についてのアイデアはありますか?
Bind()を呼び出す前に SO_REUSEADDR ソケットオプションを有効にします。これにより、アドレス/ポートを数分間TIME_WAIT状態のままにして、遅延パケットが到着するのを待つのではなく、すぐに再利用できます。
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
Windowsでは、次の手順を試すことができます。
# 4444 is your port number
netstat -ano|findstr 4444
次のようなものが得られます。
# 19088 is the PID of the process
TCP 0.0.0.0:4444 *:* 19088
と:
tskill 19088
または:
taskkill /F /PID 19088
幸運を。
@JohnKugelmanが投稿した 記事 では、SO_REUSEADDR
ソケットを使用して、以前と同じリモートエンドに接続することはできません。
SO_REUSADDRを使用すると、TIME_WAITでスタックしているポートを使用できますが、そのポートを使用して、最後に接続した場所への接続を確立することはできません。
あなたはただテスト/プレイしているだけです。ただし、このエラーを回避するには、接続を適切に終了する必要があります。オペレーティングシステムのTCPタイミングを台無しにすることもできます。 http://www.linuxquestions.org/questions/linux-networking-3/decrease-time_wait-558399/
テスト目的で、ラウンドロビン方式でserverPort
を変更するだけでも問題ありませんが、どう思いますか?
(特にWindowsでは)ソケットを閉じることが重要です。それ以外の場合は、Pythonを閉じた後、タイムアウトするまで待つ必要があります。
でしょうか:
try:
while 1:
newConnection, client = s.accept()
msg = newConnection.recv(BUFFER_SIZE)
print msg
newConnection.send("hello world")
newConnection.close()
finally:
s.close()
助けて?
サーバーコードを終了せず、別のcmdで再度実行しようとしたことが原因である可能性があります。サーバーを同じポート番号でホストすることはできません。以前にホストされていたサーバーを強制終了してください。
サーバーの最後の瞬間を停止せずにサーバーを再実行しようとすると、機能しません。現在のインスタントを停止する場合は、
シェル->シェルを再起動します
サーバーを停止せずにシェルを既に閉じている場合は、タスクマネージャーおよびタスクの終了 pythonバックグラウンドプロセッサのプロセス。サーバーの最後の瞬間を停止します。
ポート番号を別のポート番号に変更しましたが、機能します。
if __name__ == '__main__':
socketio.run(app, debug = True, use_reloader = False, port=1111)