TCP在Java中的一般應用

java裏的TCP有服務端+客戶端一說,網上搜索Server+client,那是一打一打的,內容都大同小異。但是這個一般是對於短連接來說的,但是在實際工作中,服務端和客戶端保持長連接還是比較常見的方式,這樣可以減少短連接在創建連接時所消耗的時間,對提高服務器性能起到很大的提升,但是長連接中,因爲多個數據的傳輸使用同一個通道,所以存在一個定長解析的過程(不知道是不是這麼叫法)。

看圖說話:
這裏寫圖片描述

client和server之間的傳輸方式無須多言,是雙向的。有接收就有發送。
主要要說的是所傳輸的數據結構。一般來說,數據都是通過字節流(可以理解爲byte[])的方式來體現,實際運用中,其有2部分,一是header,一是body。
header:一般是一個4個字節的定長數組,代表的是body的字節長度。
body:代表數據本身。

當client–>server發送數據時,client先封裝字節數組,包括header和body。當server接收到數據時,先讀取數據流前4個字節,轉換成整數(int類型佔4個字節)即是body數據的字節長度,然後再繼續向後讀body字節長度的數據。這樣就完成一次數據交互。

而server–>client響應數據,也是同樣的原理。這裏不再解析。

相關Java代碼:

/**
 * Created by claireliu on 2017/5/6.
 */
public class Server {

    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = new ServerSocket(9999);

        while (true) {
            Socket socket = null;
            InputStream in = null;
            OutputStream out = null;
            try {
                System.out.println("初始化。。。");
                socket = serverSocket.accept();// 從連接隊列中取出一個連接,如果沒有則等待

                System.out.println("收到請求。。。");

                in = socket.getInputStream();

                byte[] headerBuf = new byte[4];

                in.read(headerBuf);

                int bodyLength = TypeUtil.bytesToInt(headerBuf, 0);

                System.out.println("bodyLength:" + bodyLength);
                byte[] bodyBuf = new byte[bodyLength];
                in.read(bodyBuf);

                System.out.println("client said:" + new String(bodyBuf));

                out = socket.getOutputStream();

                String response = "Ok";

                byte[] responseHeaderBuf = TypeUtil.int2Bytes(response.getBytes().length);

                byte[] responseBodyBuf = response.getBytes();
                out.write(responseHeaderBuf);
                out.write(responseBodyBuf);

                out.flush();


            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(in != null) {
                    try {
                        in.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                if(out != null) {
                    try {
                        out.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                if(socket != null){
                    try {
                        socket.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }
}
public class Client {

    public static void main(String[] args) {

        InputStream in = null;
        OutputStream out = null;
        Socket socket = null;
        try{
            socket = new Socket("localhost",9999);
            out = socket.getOutputStream();

            String response = "xxx";

            System.out.println("reponse:" + response.getBytes().length);

            byte[] responseHeaderBuf = TypeUtil.int2Bytes(response.getBytes().length);

            byte[] responseBodyBuf = response.getBytes();
            out.write(responseHeaderBuf);
            out.write(responseBodyBuf);

            out.flush();

            in = socket.getInputStream();
            // 讀頭信息,即Body長度
            byte[] headerBuf = new byte[4];
            in.read(headerBuf);

            int bodyLength = TypeUtil.bytesToInt(headerBuf, 0);

            System.out.println("bodyLenth.." + bodyLength);
            byte[] bodyBuf = new byte[bodyLength];
            in.read(bodyBuf);

            // 輸出

            System.out.println("server said:" + (new String(bodyBuf)));


        }catch (Exception e){
            e.printStackTrace();

        } finally {
            if(in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

}
public class TypeUtil {


    /**
     * int返回字節數組
     * 
     * @param num
     * @return
     */
    public static byte[] int2Bytes(int num) {
        byte[] byteNum = new byte[4];
        for (int ix = 0; ix < 4; ++ix) {
            int offset = 32 - (ix + 1) * 8;
            byteNum[ix] = (byte) ((num >> offset) & 0xff);
        }
        return byteNum;
    }


    /**
     * byte數組中取int數值,本方法適用於(低位在後,高位在前)的順序。
     */
    public static int bytesToInt(byte[] src, int offset) {
        int value;
        value = (int) (((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8)
                | (src[offset + 3] & 0xFF));
        return value;
    }


}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章