//자~ 서버 소켓 생성을 쫒아가 봅시다! 포트 번호 받는 생성자~ 

0.서버 소켓의 클래스를 대충 봐야겟네요! 오...SocketImpl ??? 이걸 멤버 필드로 갖고 있네요? 뭘까 뭘까?
 
52 public class ServerSocket implements java.io.Closeable {

56     private boolean created = false;
57     private boolean bound = false;
58     private boolean closed = false;
59     private Object closeLock = new Object();

64     private SocketImpl impl;

69     private boolean oldImpl = false;

}

1.우리가 자주쓰는 포트번호 받는 생성자는 자신의 매개변수 3개짜리 생성자를 호출하는군요?
127    public ServerSocket(int port) throws IOException {
128        this(port, 50, null);
129    }

2.오호~  눈에 띄는게 setImpl()입니다? 추가로 포트 번호, 백로그가 먼진 몰라도 일단 50으로 세팅, 
  저기 237번 라인의 bind()를 잊지 맙시다!!!! 나~중에 다시 봅니다.
229    public More ...ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
230        setImpl();
231        if (port < 0 || port > 0xFFFF)
232            throw new IllegalArgumentException(
233                       "Port value out of range: " + port);
234        if (backlog < 1)
235          backlog = 50;
236        try {
237            bind(new InetSocketAddress(bindAddr, port), backlog);
238        } catch(SecurityException e) {
239            close();
240            throw e;
241        } catch(IOException e) {
242            close();
243            throw e;
244        }
245    }

3.이건 내부 초기화 메서드니까 접근자가 private군요? 
   3.1하여간 팩토리란 객체한테.. createSocketImpl(); 해달라는군요? 
   3.2팩토리 객체 없으면 SockSocketImpl() 객체를 생성하는군요? 소켓소켓? 이름도 희안하네 ㅋㅋㅋ
   3.3위에서 하여간 구현객체가 생성이 되었으니.. 초기화를 해주는군요? impl.setServerSocket(this); 
      일단 메서드 이름대로라면.. 서버소켓을 세팅하는데 매개변수로 자기 자신이 들어갑니다.
282    private void More ...setImpl() {
283        if (factory != null) {
284            impl = factory.createSocketImpl();
285            checkOldImpl();
286        } else {
287            // No need to do a checkOldImpl() here, we know it's an up to date
288            // SocketImpl!
289            impl = new SocksSocketImpl();
290        }
291        if (impl != null)
292            impl.setServerSocket(this);
293    }


4.팩토리는 무시하고 SocksSocketImpl()을 추적해봤습니다. 헐,.. 서버 소켓 생성 했습니다. 휴~


42  class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
43      private String server = null;
44      private int serverPort = DEFAULT_PORT;
45      private InetSocketAddress external_address;
46      private boolean useV4 = false;
47      private Socket cmdsock = null;
48      private InputStream cmdIn = null;  //오오 많이 보던 인풋스트림 노드계열 클래스! 현재는 비어있지만.. 반갑습니다.
49      private OutputStream cmdOut = null;  //오오 많이 보던 아웃풋스트림 노드계열 클래스!
50      /* true if the Proxy has been set programatically */
51      private boolean applicationSetProxy;  /* false */
52  
53  
54      SocksSocketImpl() {              //하여튼 저러한 필드 + 상위 클래스 필드를 포함한 소켓구현 객체 생성
55          // Nothing needed
56      }


289    void setServerSocket(ServerSocket soc) {
290        this.serverSocket = soc;         //휴~ 이제야 자신의 서버소켓에 세팅하네 -_- ㅎㄷㄷ
291    }


5.자~ 저 위에 2번에서 서버 소켓 생성을 하였으니.. 
 bind(new InetSocketAddress(bindAddr, port), backlog); 이놈을 추적해 봅니다. 좀 깁니다. 정신 단단히 붙잡고 gogo

358    public void More ...bind(SocketAddress endpoint, int backlog) throws IOException {
359        if (isClosed())
360            throw new SocketException("Socket is closed");
361        if (!oldImpl && isBound())
362            throw new SocketException("Already bound");
363        if (endpoint == null)
364            endpoint = new InetSocketAddress(0);
365        if (!(endpoint instanceof InetSocketAddress))
366            throw new IllegalArgumentException("Unsupported address type");
367        InetSocketAddress epoint = (InetSocketAddress) endpoint;
368        if (epoint.isUnresolved())
369            throw new SocketException("Unresolved address");
370        if (backlog < 1)
371          backlog = 50;

5.1자.. 위에까진 매개변수 유효성 처리였습니다. 아래의 시큐리티 매니저는 접속인증등 사용권한을 체크해주고 관리해줍니다.
중요한 메서드는 getImpl().bind() , getImpl().listen() 입니다.  독특한게.. 자신이 아까 생성한 구현체에 일을 떠맡기고
있습니다. (이게 인터페이스 클래스와 구현 클래스의 구분 목적입니다. = 추상화)

구현 객체의 bind() , listen() 을 추적하러 갑니다. 화이팅!! gogo 
참고로 구현객체 클래스는 4번에서 찾아봤지요..! 그때는 멤버 필드와 생성자만 봤었지만!

372        try {
373            SecurityManager security = System.getSecurityManager();
374            if (security != null)
375                security.checkListen(epoint.getPort());
376            getImpl().bind(epoint.getAddress(), epoint.getPort());
377            getImpl().listen(backlog);
378            bound = true;
379        } catch(SecurityException e) {
380            bound = false;
381            throw e;
382        } catch(IOException e) {
383            bound = false;
384            throw e;
385        }
386    }


6. 정신줄 놓지 않기!!! 
여기서 중요한게.. 소켓소켓임플 클래스의 상속 구조입니다. 확인! 
 class SocksSocketImpl extends PlainSocketImpl implements SocksConsts ... PlainSocketImpl을 상속 받습니다. 이름도 평범한 plain입니다.

자,.. 5번에서 추적하려던 소켓소켓임플 클래스의 bind()를 자세히 보면 매개변수가 2개 입니다.
매개변수가 2개인 bind()는 PlainSocketImpl()을 그대로 사용합니다. 그럼으로 아래의 bind()코드는 
PlainSocketImpl 클래스 파일에 정의된 메서드 입니다.

아래에서 NetHooks.beforeTcpBind(fd, address, lport); 는 파고들면 엄청 깊어짐으로 생략합니다.(sun.net 참고)
대신 애초 목적이였던 socketBind(address, lport) 를 열공 해야 합니다.


366    protected synchronized void bind(InetAddress address, int lport)
367        throws IOException
368    {
369       synchronized (fdLock) {  //멀티 스레딩을 대비해서 동기화 처리를 해주고 있습니다.
370            if (!closePending && (socket == null || !socket.isBound())) {
371                NetHooks.beforeTcpBind(fd, address, lport); //넷훅? 이름이 호기심 돋지만.. 유혹에 빠지면 안됨!
372            }
373        }
374        socketBind(address, lport); //너를 쪼개보리라!
375        if (socket != null)
376            socket.setBound();
377        if (serverSocket != null)
378            serverSocket.setBound();
379    }


7. 이런.. PlainSocketImpl 클래스에선 socketBind(매개변수 2개)를 추상 클래스로 선언했습니다. 하위클래스에
   구현이 되었겠군요?  다시 소켓소켓임플 클래스를 찾아봐야 겠습니다.
692    abstract void socketBind(InetAddress address, int port)
693        throws IOException;


****여기서 그만*****


'자바se api > net' 카테고리의 다른 글

네트워크 관련  (0) 2014.01.01
java.net.socket 파고들기1  (0) 2014.01.01
java.net 중 서버 소켓 -> IOCP -> NIO -> NODE JS + 팩토리 패턴  (0) 2014.01.01
by givingsheart 2014. 1. 1. 16:17