2017-11-02 32 views
-4

아래 프로그램을 실행할 때 bind()connect() 메서드가 즉시 예외를 throw하는 이유는 무엇입니까?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 + + 구현과 느낌을 오픈 JDK 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를 차단하는 이유는 매개 변수를 연결하는 방법입니다? 왜 블레 킹 4s ?? – Gaohongyan

+0

컴퓨터에서 테스트 할 수 있지만 문제가 서버에 연결되어 있지 않습니다. BIND() 실행이 비정상적으로 나타나면 bind() 메서드를 실행하지 않으면 connect() 메서드 블록이 4 초가 걸리므로 기본 소스가 모양을 보았고 이해할 수 없으므로 문의하십시오. – Gaohongyan

+0

귀하의 질문에 답변했습니다. 이미 내 대답을 이해하지 못한다면 나는 더 이상 당신을 도울 수 없습니다. – EJP