1. 程式人生 > >初級程式設計師不得不知道的東西

初級程式設計師不得不知道的東西

tcp的三次握手和四次揮手

 tcp的十種狀態

Java中的基於tcp協議的socket通訊(服務端)

 

Tcp服務端(第一個版本)

/**
 * Socket的服務端
 *
 *當前程式有弊端   只能為1個客戶端提供服務
 *
 */
public class MyServerSocket01 {
    /**
     * 程式的執行入口
     *
     * @param args 傳遞的引數
     */
    public static void main(String[] args) throws Exception {

        //建立服務端的Socket物件
        ServerSocket serverSocket = new ServerSocket();
        //服務端繫結埠
        serverSocket.bind(new InetSocketAddress(8899));
        //監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
        Socket socket = serverSocket.accept();
        System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
        InputStream inputStream = socket.getInputStream();
        //讀資料
        byte[] buf = new byte[2];
        int len;
        //呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
        while ((len = inputStream.read(buf)) != -1) {
            String str = new String(buf, 0, len);
            System.out.println(str);
        }
    }
}

Tcp服務端(第二個版本)

/**
 * Socket的服務端
 * 當前程式有弊端   只能為一個客戶端提供服務,只不過一個客戶端斷開連線之後其他的客戶端才能進來
 */
public class MyServerSocket02 {
    /**
     * 程式的執行入口
     *
     * @param args 傳遞的引數
     */
    public static void main(String[] args) throws Exception {
        //建立服務端的Socket物件
        ServerSocket serverSocket = new ServerSocket();
        //服務端繫結埠
        serverSocket.bind(new InetSocketAddress(8899));
        while (true) {
            //監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
            Socket socket = serverSocket.accept();
            System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
            InputStream inputStream = socket.getInputStream();
            //讀資料
            byte[] buf = new byte[2];
            int len;
            //呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
            while ((len = inputStream.read(buf)) != -1) {
                String str = new String(buf, 0, len);
                System.out.println(str);
            }
        }
    }
}

Tcp服務端(第三個版本)

/**
 * Socket的服務端
 * 當前程式有弊端   每次一個客戶端進來之後都會建立一個執行緒去處理連線任務,但有大量的客戶端連線到伺服器的話就會有大量的執行緒建立,執行緒的建立和上下文的切換也是非常耗費時間和資源的
 */
public class MyServerSocket02 {
    /**
     * 程式的執行入口
     *
     * @param args 傳遞的引數
     */
    public static void main(String[] args) throws Exception {
        //建立服務端的Socket物件
        ServerSocket serverSocket = new ServerSocket();
        //服務端繫結埠
        serverSocket.bind(new InetSocketAddress(8899));
        while (true) {
            //監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
            Socket socket = serverSocket.accept();
            //每次有新的客戶端連線到伺服器之後都會啟動執行緒來執行
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
                    InputStream inputStream = null;
                    try {
                        inputStream = socket.getInputStream();
                        //讀資料
                        byte[] buf = new byte[2];
                        int len;
                        //呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
                        while ((len = inputStream.read(buf)) != -1) {
                            String str = new String(buf, 0, len);
                            System.out.println(str);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

Tcp服務端(第四個版本)

/**
 * Socket的服務端
 * 當前程式有弊端   有兩個阻塞  accept  read,其中accept我們就無法解決,但是read阻塞可以解決的(NIO)
 */
public class MyServerSocket04 {
    /**
     * 程式的執行入口
     *
     * @param args 傳遞的引數
     */
    public static void main(String[] args) throws Exception {
        //建立執行緒池物件(執行緒池的大小是本機的cpu可用的核數)
        ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        //建立服務端的Socket物件
        ServerSocket serverSocket = new ServerSocket();
        //服務端繫結埠
        serverSocket.bind(new InetSocketAddress(8899));
        while (true) {
            //監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
            Socket socket = serverSocket.accept();
            //每次有新的客戶端連線到伺服器之後都會啟動執行緒來執行
            threadPool.execute(new Runnable() {
                @Override
                public void run() {

                    System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
                    InputStream inputStream = null;
                    try {
                        inputStream = socket.getInputStream();
                        //讀資料
                        byte[] buf = new byte[2];
                        int len;
                        //呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
                        while ((len = inputStream.read(buf)) != -1) {
                            String str = new String(buf, 0, len);
                            System.out.println(str);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}