Socket-TCP數(shù)據(jù)傳輸

1绘盟、TCP

  • 傳輸層的控制協(xié)議
  • 面向連接的倍权、可靠的、基于字節(jié)流的傳輸層通信協(xié)議
  • 與UDP一樣完成第四層傳輸層所指定的功能與職責(zé)

2囱修、應(yīng)用

  • 聊天消息傳輸赎瑰、推送
  • 單人語音、視頻聊天
  • UDP能做的破镰,TCP幾乎都能做餐曼。需要考慮復(fù)雜性、性能問題
  • 限制:無法廣播鲜漩、多播操作源譬;無法搜索客戶端

3、可靠性

  • 連接可靠性:三次握手孕似,四次揮手
  • 傳輸可靠性:排序踩娘、丟棄(超時(shí))、重發(fā)

4喉祭、Client

public class Client {
    private static final int PORT = 20000;
    private static final int LOCAL_PORT = 20001;

    public static void main(String[] args) throws IOException {
        Socket socket = createSocket();

        initSocket(socket);

        // 鏈接到本地20000端口(指連接服務(wù)器端口)养渴,超時(shí)時(shí)間3秒,超過則拋出超時(shí)異常
        socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 3000);

        System.out.println("已發(fā)起服務(wù)器連接泛烙,并進(jìn)入后續(xù)流程~");
        System.out.println("客戶端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort());
        System.out.println("服務(wù)器信息:" + socket.getInetAddress() + " P:" + socket.getPort());

        try {
            // 發(fā)送接收數(shù)據(jù)
            todo(socket);
        } catch (Exception e) {
            System.out.println("異常關(guān)閉");
        }

        // 釋放資源
        socket.close();
        System.out.println("客戶端已退出~");

    }

    private static Socket createSocket() throws IOException {
        Socket socket = new Socket();
        // 綁定到本地20001端口(綁定客戶端端口理卑,不綁定的話會(huì)隨機(jī)分配一個(gè)端口給客戶端)
        socket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), LOCAL_PORT));

        return socket;
    }

    private static void initSocket(Socket socket) throws SocketException {
        // 設(shè)置讀取超時(shí)時(shí)間為2秒
        socket.setSoTimeout(2000);

        // 是否復(fù)用未完全關(guān)閉的Socket地址,對(duì)于指定bind操作后的套接字有效
        socket.setReuseAddress(true);

        // 是否開啟Nagle算法
        socket.setTcpNoDelay(true);

        // 是否需要在長(zhǎng)時(shí)無數(shù)據(jù)響應(yīng)時(shí)發(fā)送確認(rèn)數(shù)據(jù)(類似心跳包)蔽氨,時(shí)間大約為2小時(shí)
        socket.setKeepAlive(true);

        // 對(duì)于close關(guān)閉操作行為進(jìn)行怎樣的處理藐唠;默認(rèn)為false,0
        // false鹉究、0:默認(rèn)情況中捆,關(guān)閉時(shí)立即返回,底層系統(tǒng)接管輸出流坊饶,將緩沖區(qū)內(nèi)的數(shù)據(jù)發(fā)送完成
        // true泄伪、0:關(guān)閉時(shí)立即返回,緩沖區(qū)數(shù)據(jù)拋棄匿级,直接發(fā)送RST結(jié)束命令到對(duì)方蟋滴,并無需經(jīng)過2MSL等待
        // true、200:關(guān)閉時(shí)最長(zhǎng)阻塞200毫秒痘绎,隨后按第二情況處理
        socket.setSoLinger(true, 20);

        // 是否讓緊急數(shù)據(jù)內(nèi)斂津函,默認(rèn)false;緊急數(shù)據(jù)通過 socket.sendUrgentData(1);發(fā)送
        socket.setOOBInline(false);

        // 設(shè)置接收發(fā)送緩沖器大小
        socket.setReceiveBufferSize(64 * 1024 * 1024);
        socket.setSendBufferSize(64 * 1024 * 1024);

        // 設(shè)置性能參數(shù):短鏈接孤页,延遲尔苦,帶寬的相對(duì)重要性
        socket.setPerformancePreferences(1, 1, 0);
    }

    private static void todo(Socket client) throws IOException {
        // 得到Socket輸出流
        OutputStream outputStream = client.getOutputStream();


        // 得到Socket輸入流
        InputStream inputStream = client.getInputStream();
        byte[] buffer = new byte[256];
        ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);

        // byte
        byteBuffer.put((byte) 126);

        // char
        char c = 'a';
        byteBuffer.putChar(c);

        // int
        int i = 2323123;
        byteBuffer.putInt(i);

        // bool
        boolean b = true;
        byteBuffer.put(b ? (byte) 1 : (byte) 0);

        // Long
        long l = 298789739;
        byteBuffer.putLong(l);


        // float
        float f = 12.345f;
        byteBuffer.putFloat(f);


        // double
        double d = 13.31241248782973;
        byteBuffer.putDouble(d);

        // String
        String str = "Hello你好!";
        byteBuffer.put(str.getBytes());

        // 發(fā)送到服務(wù)器
        outputStream.write(buffer, 0, byteBuffer.position() + 1);

        // 接收服務(wù)器返回
        int read = inputStream.read(buffer);
        System.out.println("收到數(shù)量:" + read);

        // 資源釋放
        outputStream.close();
        inputStream.close();
    }
}

5、Server

public class Server {
    private static final int PORT = 20000;

    public static void main(String[] args) throws IOException {
        ServerSocket server = createServerSocket();

        initServerSocket(server);

        // 綁定到本地端口上(綁定調(diào)用相當(dāng)于服務(wù)已經(jīng)啟動(dòng)允坚,最大等待連接客戶端數(shù)為50魂那,超過則拋出異常)
        server.bind(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 50);


        System.out.println("服務(wù)器準(zhǔn)備就緒~");
        System.out.println("服務(wù)器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());


        // 等待客戶端連接
        for (; ; ) {
            // 得到客戶端
            Socket client = server.accept();
            // 客戶端構(gòu)建異步線程
            ClientHandler clientHandler = new ClientHandler(client);
            // 啟動(dòng)線程
            clientHandler.start();
        }

    }

    private static ServerSocket createServerSocket() throws IOException {
        // 創(chuàng)建基礎(chǔ)的ServerSocket
        ServerSocket serverSocket = new ServerSocket();

        // 綁定到本地端口20000上,并且設(shè)置當(dāng)前可允許等待鏈接的隊(duì)列為50個(gè)稠项,相當(dāng)于服務(wù)已經(jīng)啟動(dòng)
        //serverSocket = new ServerSocket(PORT);

        // 等效于上面的方案涯雅,隊(duì)列設(shè)置為50個(gè)
        //serverSocket = new ServerSocket(PORT, 50);

        // 與上面等同
        // serverSocket = new ServerSocket(PORT, 50, Inet4Address.getLocalHost());

        return serverSocket;
    }

    private static void initServerSocket(ServerSocket serverSocket) throws IOException {
        // 是否復(fù)用未完全關(guān)閉的地址端口
        serverSocket.setReuseAddress(true);

        // 等效Socket#setReceiveBufferSize
        serverSocket.setReceiveBufferSize(64 * 1024 * 1024);

        // 設(shè)置serverSocket#accept超時(shí)時(shí)間
        // serverSocket.setSoTimeout(2000);

        // 設(shè)置性能參數(shù):短鏈接,延遲展运,帶寬的相對(duì)重要性
        serverSocket.setPerformancePreferences(1, 1, 1);
    }

    /**
     * 客戶端消息處理
     */
    private static class ClientHandler extends Thread {
        private Socket socket;

        ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            super.run();
            System.out.println("新客戶端連接:" + socket.getInetAddress() +
                    " P:" + socket.getPort());

            try {
                // 得到套接字流
                OutputStream outputStream = socket.getOutputStream();
                InputStream inputStream = socket.getInputStream();

                byte[] buffer = new byte[256];
                int readCount = inputStream.read(buffer);
                ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, readCount);

                // byte
                byte be = byteBuffer.get();

                // char
                char c = byteBuffer.getChar();

                // int
                int i = byteBuffer.getInt();

                // bool
                boolean b = byteBuffer.get() == 1;

                // Long
                long l = byteBuffer.getLong();

                // float
                float f = byteBuffer.getFloat();

                // double
                double d = byteBuffer.getDouble();

                // String
                int pos = byteBuffer.position();
                String str = new String(buffer, pos, readCount - pos - 1);

                System.out.println("收到數(shù)量:" + readCount + " 數(shù)據(jù):"
                        + be + "\n"
                        + c + "\n"
                        + i + "\n"
                        + b + "\n"
                        + l + "\n"
                        + f + "\n"
                        + d + "\n"
                        + str + "\n");

                outputStream.write(buffer, 0, readCount);
                outputStream.close();
                inputStream.close();

            } catch (Exception e) {
                System.out.println("連接異常斷開");
            } finally {
                // 連接關(guān)閉
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            System.out.println("客戶端已退出:" + socket.getInetAddress() +
                    " P:" + socket.getPort());

        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末活逆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拗胜,更是在濱河造成了極大的恐慌蔗候,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埂软,死亡現(xiàn)場(chǎng)離奇詭異琴庵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)仰美,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門迷殿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人咖杂,你說我怎么就攤上這事庆寺。” “怎么了诉字?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵懦尝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我壤圃,道長(zhǎng)陵霉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任伍绳,我火速辦了婚禮踊挠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冲杀。我一直安慰自己效床,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布权谁。 她就那樣靜靜地躺著剩檀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旺芽。 梳的紋絲不亂的頭發(fā)上沪猴,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天辐啄,我揣著相機(jī)與錄音,去河邊找鬼运嗜。 笑死壶辜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洗出。 我是一名探鬼主播士复,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼图谷,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼翩活!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起便贵,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤菠镇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后承璃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體利耍,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年盔粹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了隘梨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舷嗡,死狀恐怖轴猎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情进萄,我是刑警寧澤捻脖,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站中鼠,受9級(jí)特大地震影響可婶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜援雇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一矛渴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惫搏,春花似錦曙旭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至川陆,卻和暖如春剂习,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工鳞绕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留失仁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓们何,卻偏偏與公主長(zhǎng)得像萄焦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冤竹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)鹦蠕。冒签。。钟病。萧恕。。肠阱。票唆。 SOCKET,TCP/UDP,HTTP,FTP (一)TCP/UDP,SOCKET,HTTP,...
    zeqinjie閱讀 3,295評(píng)論 1 53
  • 1.這些都是什么? 既然是網(wǎng)絡(luò)傳輸,涉及幾個(gè)系統(tǒng)之間的交互缘回,那么首先要考慮的是如何準(zhǔn)確的定位到網(wǎng)絡(luò)上的一臺(tái)或者幾臺(tái)...
    Coder_Fsh_Messi閱讀 3,136評(píng)論 0 43
  • # 圖解TCP/IP 標(biāo)簽(空格分隔): 2018招聘 --- ##第1章 網(wǎng)絡(luò)基礎(chǔ)知識(shí) ### ### 1.1 ...
    Kai_a3da閱讀 1,451評(píng)論 0 2
  • 很想掏個(gè)心出來跟你講吆视,讓你安心,但是我不能畢竟你已經(jīng)很膨脹了酥宴。 我也想要一直跟你走下去啦吧。
    Sela_閱讀 245評(píng)論 0 0
  • 最近自我感覺對(duì)文字的輸出越來越少了,所謂文字是對(duì)自己思想的另外一種表達(dá)拙寡。比如你去一家企業(yè)面試授滓,除去片面最基...
    洋宇之聲閱讀 1,131評(píng)論 0 1