Java套接字編程


實現了基於TCP的Java Socket編程實例代碼:簡單實現了服務器和客戶端的套接字編程,並傳遞簡單的字符串。(在服務器聲明套接字時需要綁定服務器的端口,端口為臨界資源只能一個套接字使用。服務器編程時調用accept()方法,服務器進入等待連接狀態。)

Java中TCP/IP服務端連接建立的源碼實現(socket->bind->listen->accept):

(1)在進行套接字編程的時候,首先我們要建立一個服務端,並在服務端建立套接字,為套接字綁定接口,然后監聽客戶端可能發來的連接建立請求。這一套流程均在ServerSocket的構造時完成(這里需要說明的是Java中的Socket和ServerSocket均是實現的java.io.Closeable接口。下面我們來看下構造函數中是如何實現端口的綁定和連接的監聽的: 

public ServerSocket(int port) throws IOException {
        this(port, 50, null);
    }

  對於只有端口輸入的構造函數來說,我們復用另一個構造函數:ServerSocket(int port, int backlog, InetAddress bindAddr)。其中port是綁定的端口號,backlog是最大連接並發數,默認為50。bindAddr是被綁定的當地IP地址。

public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
        setImpl();
        if (port < 0 || port > 0xFFFF)
            throw new IllegalArgumentException(
                       "Port value out of range: " + port);
        if (backlog < 1)
          backlog = 50;
        try {
            bind(new InetSocketAddress(bindAddr, port), backlog);
        } catch(SecurityException e) {
            close();
            throw e;
        } catch(IOException e) {
            close();
            throw e;
        }
    }
View Code

  我們可以看到在這個構造函數中有bind(new InetSocketAddress(bindAddr, port), backlog)這句代碼,這就是用來進行IP地址和端口綁定的,我們在使用套接字時可以只設置端口,則IP地址默認為null。進入到bind方法中:

public void bind(SocketAddress endpoint, int backlog) throws IOException {
       ......
        try {
            SecurityManager security = System.getSecurityManager();
            if (security != null)
                security.checkListen(epoint.getPort());
            getImpl().bind(epoint.getAddress(), epoint.getPort());
            getImpl().listen(backlog);
            bound = true;
        } catch(SecurityException e) {
            bound = false;
            throw e;
        } catch(IOException e) {
            bound = false;
            throw e;
        }
    }

  被我省略的代碼主要是進行安全檢查的工作,查看端口是否已經關閉或被占用,傳進來的地址是否合法等,並提供了相應的處理方法。而try包裹的就是核心的東西了。這里涉及到SecurityManager、SocketImpl類,目前並不了解。不過我們可以看到的bind和listen字段應該就是套接字准備進入阻塞狀態的代碼了(因為后面還要調用accept,所以我猜測到這一步並沒有進入阻塞狀態)。

  后面的accept方法又涉及到不知道的類,我等查碩就先不找虐了,先寫到這,后面看熟了再總結。

(2)至於服務套接字寫好后,客戶端是如何進行連接的,其實也是在構造階段就完成的(socket->connect),下面列出相關源碼,以后在做分析。(connect是主動建立連接的方法,這說明每個類型的請求都需要編程一個套接字,客戶端與服務端在這時是多對一的關系)

public Socket(String host, int port)
        throws UnknownHostException, IOException
    {
        this(host != null ? new InetSocketAddress(host, port) :
             new InetSocketAddress(InetAddress.getByName(null), port),
             (SocketAddress) null, true);
    }

   其中host是IP地址,port是端口號。

private Socket(SocketAddress address, SocketAddress localAddr,
                   boolean stream) throws IOException {
        setImpl();

        // backward compatibility
        if (address == null)
            throw new NullPointerException();

        try {
            createImpl(stream);
            if (localAddr != null)
                bind(localAddr);
            connect(address);
        } catch (IOException | IllegalArgumentException | SecurityException e) {
            try {
                close();
            } catch (IOException ce) {
                e.addSuppressed(ce);
            }
            throw e;
        }
    }
View Code

  見到connect方法足矣,就不往下跟蹤了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM