2016-11-28 6 views
4

SocketとServerSocketのポート使用について混乱します。 Oracle's java tutorial about socketsは、次の言葉:クライアントを受け入れた後、Java ServerSocketは新しいソケットを同じローカルポートにバインドする方法を教えてください。

ソケットですか?

通常、サーバーは特定のコンピュータで動作し、特定のポート番号にバインドされたソケットを持っています。サーバーは、クライアントが接続要求を行うためにソケットを待機するだけです。 クライアント側:クライアントは、サーバーが稼動しているマシンのホスト名と、サーバーがリスンしているポート番号を知っています。接続要求を行うために、クライアントはサーバーのマシンとポート上のサーバーとのランデブーを試みます。また、クライアントはサーバーに自身を識別させる必要があるため、この接続中に使用するローカルポート番号にバインドします。これは、通常、システムによって割り当てられます。

すべてがうまくいくと、サーバーは接続を受け入れます。 受諾時に、サーバーは同じローカルポート にバインドされた新しいソケットを取得し、リモートエンドポイントも クライアントのアドレスとポートに設定します。 接続されたクライアントのニーズに対応しながら、接続要求のために元のソケット を引き続き受信できるように、新しいソケットが必要です。

クライアント側では、接続が受け入れられるとソケットが正常に作成され、クライアントはソケットを使用してサーバーと通信できます。 クライアントとサーバーは、ソケットへの書き込みまたはソケットからの読み取りによって通信できるようになりました。

次のコードを試してみました。しかし例外をスローします。

try { 
    ServerSocket serverSocket = new ServerSocket(8080); 

    Socket socket = serverSocket.accept(); 

    // This prints 8080 
    System.out.println("Local port of accepted socket : " + socket.getLocalPort()); 

    // But this throws java.net.BindException: Address already in use: JVM_Bind 
    Socket myClientSocket = new Socket("www.google.com", 80, null, 8080); 

} catch (Exception e) { 
    e.printStackTrace(); 
} 

私の質問は明らかです。 serverSocket.accept()から返されたソケットは、同じローカルポート(8080)を使用できますが、なぜ私が作成したソケットは使用できませんか?

+0

それは彼らがそれを設計した方法なので。引用していることを明確にしてください。 – EJP

答えて

-1

サーバーとクライアントが同じローカルポートを使用して通信しています。サーバーソケットを作成したときは、「8080ポートでリッスンする必要があります。それで大丈夫です。サーバーソケットと通信したい人は、そのようなポートを使用する必要があります。

しかし、あなたの下には、ポート80(googleはそのポートでリッスンしています)を使用してGoogleサイトに接続するクライアントソケットが作成されています。最後の引数では、このソケットはローカルポート8080を使用して接続を確立します。一度に1つの接続しか使用できないため、java.net.BindExceptionが発生しています。サーバーとクライアントの両方の接続で8080が使用されています。

私の提案...

Socket myClientSocket = new Socket("www.google.com", 80); 

または

Socket myClientSocket = new Socket("www.google.com", 80, null, 58080); 
+0

サーバは、「accept」サーバで作成されたポートがローカルポート「8080」を持つことが許可されている場合、*なぜ*これが起きるかを質問しています。 – RealSkeptic

+0

私はこう答えました。「一度に1つのプロセスしかポートを使用できないため、java.net.BindExceptionを取得しています。彼はサーバーとクライアントの両方に8080のローカルポート(インバウンドとアウトバウンド)を使用しています – RLM

+0

@RaphaelMoitaこのコードはすべて同じプロセスで実行されています。あなたはその質問に答えなかった。 – EJP

1

保つために:(常に他のプロセスと同じ問題を回避するために、高い番号を取得)しますソケットクライアントのコンストラクタからの最後の2つの引数を取り、またはあなたのローカルクライアントポートを変更します受信TCPソケットはすでに明示的にポートにバインドされているため、2つ目のTCPソケットを同じポートに明示的にバインドすることはできません(両方のソケットがINADDR_ANYを除く異なるIPアドレスに明示的にバインドされている場合を除きます)。

受け入れられたソケットは、明示的な「バインド」プロセスを経由しません。バインディングなしで接続するとアウトバウンドソケットと同様にローカルIPアドレスとポートを自動的に取得します。

+0

@RaphaelMoitaあなたのポイントは私を逃げる。 – EJP

関連する問題