2017-11-02 9 views
-4

以下のプログラムを実行すると、bind()およびconnect()のメソッドはただちに例外をスローします。Javaソケット:bind()およびconnect()メソッドの問題

bind()メソッドを使用しない場合、connect()メソッドは4秒間実行をブロックしています。理由は何でしょうか?

package test1; 

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.net.Socket; 

public class Test73 { 
    public static void main(String[] args) throws IOException { 
     long beginTime = 0; 
     try { 
      Socket socket = new Socket(); 
      System.out.println(socket.getPort()); 
      System.out.println(socket.getLocalPort()); 
      // socket.bind(new InetSocketAddress("localhost", 7777)); 
      System.out.println(socket.getPort()); 
      System.out.println(socket.getLocalPort()); 
      beginTime = System.currentTimeMillis(); 
      socket.connect(new InetSocketAddress("1.1.1.1", 8888), 4000); 
      System.out.println(socket.getPort()); 
      System.out.println(socket.getLocalPort()); 
      socket.close(); 
      System.out.println("client end!"); 
     } catch (Exception e) { 
      long endTime = System.currentTimeMillis(); 
      System.out.println(endTime - beginTime); 
      e.printStackTrace(); 
     } 
    } 

} 

下のコードは、ネイティブソースコードです、それは私が基礎となるC + +の実装と感じるOpenJDKのsource.Thisの問題なので、下のソースコードが掲載されています!

JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect 
    (JNIEnv *env, jclass clazz, jint fd, jint timeout) { 
    int rv, retry; 
    int optlen = sizeof(rv); 
    fd_set wr, ex; 
    struct timeval t; 

    FD_ZERO(&wr); 
    FD_ZERO(&ex); 
    FD_SET(fd, &wr); 
    FD_SET(fd, &ex); 
    t.tv_sec = timeout/1000; 
    t.tv_usec = (timeout % 1000) * 1000; 

    /* 
    * Wait for timeout, connection established or 
    * connection failed. 
    */ 
    rv = select(fd+1, 0, &wr, &ex, &t); 

    /* 
    * Timeout before connection is established/failed so 
    * we throw exception and shutdown input/output to prevent 
    * socket from being used. 
    * The socket should be closed immediately by the caller. 
    */ 
    if (rv == 0) { 
     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", 
         "connect timed out"); 
     shutdown(fd, SD_BOTH); 
     return; 
    } 

    /* 
    * Socket is writable or error occurred. On some Windows editions 
    * the socket will appear writable when the connect fails so we 
    * check for error rather than writable. 
    */ 
    if (!FD_ISSET(fd, &ex)) { 
     return;   /* connection established */ 
    } 

    /* 
    * Connection failed. The logic here is designed to work around 
    * bug on Windows NT whereby using getsockopt to obtain the 
    * last error (SO_ERROR) indicates there is no error. The workaround 
    * on NT is to allow winsock to be scheduled and this is done by 
    * yielding and retrying. As yielding is problematic in heavy 
    * load conditions we attempt up to 3 times to get the error reason. 
    */ 
    for (retry=0; retry<3; retry++) { 
     NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, 
         (char*)&rv, &optlen); 
     if (rv) { 
      break; 
     } 
     Sleep(0); 
    } 

    if (rv == 0) { 
     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", 
         "Unable to establish connection"); 
    } else { 
     NET_ThrowNew(env, rv, "connect"); 
    } 
} 

答えて

1

127.0.0.1にバインドすると、同じホストのローカルアドレスにしか接続できないため、1.1.1.1に接続できません。バインドしない場合、connect()は、ターゲットアドレスにルーティングできる適切なローカルアドレスをバインドすることを選択します。

connect()は、瞬間的な操作ではありません。3方向パケット交換が必要です。この場合、1.1.1.1にも接続できませんでしたので、指定した4000msの接続タイムアウトが得られました。

+0

EJP〜ありがとうございます〜ですが質問は接続方法タイムアウトパラメータです、なぜ4sをブロックしますか?なぜ駄目なの? – Gaohongyan

+0

私の問題はサーバーに接続されていない、コンピュータ上でテストすることができます。 bind()メソッドを実行しないとconnect()メソッドブロックが4秒間ブロックされ、BIND()の実行がすぐに異常なように見える場合は、ネイティブソースが一見を見ています。 – Gaohongyan

+0

私はあなたの質問に答えました。あなたの答えがすでに書かれているように理解できない場合、私はあなたをさらに助けることはできません。 – EJP

関連する問題