2011-02-09 5 views
21

マシンはRHEL 5.3(カーネル2.6.18)です。私は自分のアプリケーションが接続を持っているのnetstatに気づくどのようにして同じポートにTCP接続を戻すことができますか?

いくつかの回、確立されたTCP接続ローカルアドレス外国住所は同じです。

Here他の人からも同じ問題が報告されています。

症状は、ローカルで実行されているサーバのport-to-port接続のリンククライアントで説明したのと同じです。しばらくすると、クライアントが接続していることがnetstatによって示されます127.0.0.1:Xから127.0.0.1:X

どうすれば可能ですか?

編集01

同時オープンが(多くHasturkunのおかげで)問題を引き起こしています。 classical TCP state diagramでSYN_SENT状態からSYNC_RECEIVEDに遷移しています

+0

症状は、ローカルで実行されているサーバーのポートXポートへのリンクのリンクで説明されているのと同じです。しばらくしてnetstatは、クライアントが127.0.0.1:Xから127.0.0.1:X – dimba

答えて

17

これは、TCP同時接続(on this post to LKMLを参照、hereも参照してください)によって発生する可能性があります。

動的ローカルポート範囲(/proc/sys/net/ipv4/ip_local_port_rangeに示されている)内のポートに接続しようとすると、サーバーがそのポートでリッスンしていない間にループする可能性があります。

十分な数の試行では、接続に使用されているソケットは、接続先の同じポートにバインドされている可能性があります。

+0

+1これは私の問題の私の原因になる可能性があります – dimba

+0

実際に私のクライアントは、サーバーがダウンしている場合、常にサーバーに接続しようとします。ですから、どうやってそのような状況を防ぐことができるのでしょうか?/proc/sys/net/ipv4/ip_local_port_rangeの範囲にないポートをサーバが使用する必要があるのでしょうか? – dimba

+0

@dimba:はい、サーバーがその範囲の下限より低いポートをリッスンすると、この問題は完全に防ぎます – Hasturkun

12

TCP接続はこのタプル(local address, local port #, foreign address, foreign port #)によって一意に識別されます。 local addressforeign addressという要件はなく、ポート番号が異なることもあります(ただし、それは非常に奇妙です)。しかし、与えられたタプルに対して同じ値を持つTCP接続は最大でも1つしかありません。

コンピュータが接続するとき、ローカルアドレスと外部アドレスはほとんど同じです。結局のところ、「ローカル」側と「外国側」は実際は同じコンピュータです。実際には、これが起こるときあなたのコンピュータは同じ「ローカル」および「外国人」のアドレスを有するが、ポート番号を逆にした2つの接続を示しているはずである。たとえば:

$ ssh localhost 

は次のようになり、2つの接続になります:

$ netstat -nA inet | fgrep :22 
Active Internet connections (w/o servers) 
Proto Recv-Q Send-Q Local Address  Foreign Address  State  
tcp  0  0 127.0.0.1:56039  127.0.0.1:22   ESTABLISHED 
tcp  0  0 127.0.0.1:22   127.0.0.1:56039  ESTABLISHED 

あなたが見ることができるように、ローカルアドレスと外部のアドレスは同じですが、ポート番号が逆になっています。このTCP接続の一意のタプルは(127.0.0.1, 56039, 127.0.0.1, 22)です。これらの同じ4つのフィールドを持つ他のTCP接続はありません。

あなたのコンピュータが接続の両端であることが原因で2つが表示されます。それぞれの終わりには、どちらかが「外国人」であり、「ローカル」であるという独自の見解があります。

同じポート上で自分自身に接続することもできますが、これは一般的な現象ではありませんが、仕様では禁止されていません。ここでこれを行いますPythonでのサンプル・プログラムは次のとおりです。

import socket 
import time 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind(('127.0.0.1', 56443)) 
s.connect(('127.0.0.1', 56443)) 
time.sleep(30) 

それがTCP接続を開くことができます1つの方法は、接続の反対側が同時にあなたと1を開こうとすることですので、このコードは動作します。これはsimultaneous SYN exchangeとして知られており、StackOverflowの回答にリンクされていると、その内容が説明されています。

私はまた、using simultaneous SYN exchange to get through NATについての論文を持っていますが、その場合、ソースと外国語は全く異なるでしょう。

+0

に接続していることを示しています。しかし、どのようにクライアントが最終的に同じポートのサーバーを開くのか(ポストのリンクを参照)結果サーバーは既に使用中のサーバーポートを開くことができません。 – dimba

+0

AFAIK、私は意図的に同じポートから同じポートに接続しません – dimba

+0

@dimba - これを実現する方法を示すコードがあります。誰かがそのようなことをする理由が別の質問です。しかし確かに可能です。 – Omnifarious

関連する問題