成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Android網(wǎng)絡(luò)編程之Socket

The question / 2473人閱讀

摘要:面向字節(jié)流流,指的是流入到進(jìn)程或從進(jìn)程流出的字符序列。即收到連接信息后向返回確認(rèn)信息第三次握手客戶端收到服務(wù)器的報(bào)文段,并向服務(wù)器發(fā)送報(bào)文段。

前言

Socket的使用在 Android網(wǎng)絡(luò)編程中非常重要

今天我將帶大家全面了解 Socket 及 其使用方法

目錄

1.網(wǎng)絡(luò)基礎(chǔ) 1.1 計(jì)算機(jī)網(wǎng)絡(luò)分層

計(jì)算機(jī)網(wǎng)絡(luò)分為五層:物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、運(yùn)輸層、應(yīng)用層

其中:

網(wǎng)絡(luò)層:負(fù)責(zé)根據(jù)IP找到目的地址的主機(jī)

運(yùn)輸層:通過端口把數(shù)據(jù)傳到目的主機(jī)的目的進(jìn)程,來實(shí)現(xiàn)進(jìn)程與進(jìn)程之間的通信

1.2 端口號(hào)(PORT)

端口號(hào)規(guī)定為16位,即允許一個(gè)IP主機(jī)有2的16次方65535個(gè)不同的端口。其中:

0~1023:分配給系統(tǒng)的端口號(hào)

> 我們不可以亂用

1024~49151:登記端口號(hào),主要是讓第三方應(yīng)用使用

> 但是必須在IANA(互聯(lián)網(wǎng)數(shù)字分配機(jī)構(gòu))按照規(guī)定手續(xù)登記,

49152~65535:短暫端口號(hào),是留給客戶進(jìn)程選擇暫時(shí)使用,一個(gè)進(jìn)程使用完就可以供其他進(jìn)程使用。

在Socket使用時(shí),可以用1024~65535的端口號(hào)

1.3 C/S結(jié)構(gòu)

定義:即客戶端/服務(wù)器結(jié)構(gòu),是軟件系統(tǒng)體系結(jié)構(gòu)

作用:充分利用兩端硬件環(huán)境的優(yōu)勢(shì),將任務(wù)合理分配到Client端和Server端來實(shí)現(xiàn),降低了系統(tǒng)的通訊開銷。

> Socket正是使用這種結(jié)構(gòu)建立連接的,一個(gè)套接字接客戶端,一個(gè)套接字接服務(wù)器。

如圖:

可以看出,Socket的使用可以基于TCP或者UDP協(xié)議。

1.4 TCP協(xié)議

定義:Transmission Control Protocol,即傳輸控制協(xié)議,是一種傳輸層通信協(xié)議

基于TCP的應(yīng)用層協(xié)議有FTP、Telnet、SMTP、HTTP、POP3與DNS。

特點(diǎn):面向連接、面向字節(jié)流、全雙工通信、可靠

面向連接:指的是要使用TCP傳輸數(shù)據(jù),必須先建立TCP連接,傳輸完成后釋放連接,就像打電話一樣必須先撥號(hào)建立一條連接,打完后掛機(jī)釋放連接。

全雙工通信:即一旦建立了TCP連接,通信雙方可以在任何時(shí)候都能發(fā)送數(shù)據(jù)。

可靠的:指的是通過TCP連接傳送的數(shù)據(jù),無差錯(cuò),不丟失,不重復(fù),并且按序到達(dá)。

面向字節(jié)流:流,指的是流入到進(jìn)程或從進(jìn)程流出的字符序列。簡(jiǎn)單來說,雖然有時(shí)候要傳輸?shù)臄?shù)據(jù)流太大,TCP報(bào)文長(zhǎng)度有限制,不能一次傳輸完,要把它分為好幾個(gè)數(shù)據(jù)塊,但是由于可靠性保證,接收方可以按順序接收數(shù)據(jù)塊然后重新組成分塊之前的數(shù)據(jù)流,所以TCP看起來就像直接互相傳輸字節(jié)流一樣,面向字節(jié)流。

TCP建立連接
必須進(jìn)行三次握手:若A要與B進(jìn)行連接,則必須

第一次握手:建立連接??蛻舳税l(fā)送連接請(qǐng)求報(bào)文段,將SYN位置為1,Sequence Number為x;然后,客戶端進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器的確認(rèn)。即A發(fā)送信息給B

第二次握手:服務(wù)器收到客戶端的SYN報(bào)文段,需要對(duì)這個(gè)SYN報(bào)文段進(jìn)行確認(rèn)。即B收到連接信息后向A返回確認(rèn)信息

第三次握手:客戶端收到服務(wù)器的(SYN+ACK)報(bào)文段,并向服務(wù)器發(fā)送ACK報(bào)文段。即A收到確認(rèn)信息后再次向B返回確認(rèn)連接信息

> 此時(shí),A告訴自己上層連接建立;B收到連接信息后告訴上層連接建立。

這樣就完成TCP三次握手 = 一條TCP連接建立完成 = 可以開始發(fā)送數(shù)據(jù)

三次握手期間任何一次未收到對(duì)面回復(fù)都要重發(fā)。

最后一個(gè)確認(rèn)報(bào)文段發(fā)送完畢以后,客戶端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài)。

為什么TCP建立連接需要三次握手?

答:防止服務(wù)器端因?yàn)榻邮樟?strong>早已失效的連接請(qǐng)求報(bào)文從而一直等待客戶端請(qǐng)求,從而浪費(fèi)資源

“已失效的連接請(qǐng)求報(bào)文段”的產(chǎn)生在這樣一種情況下:Client發(fā)出的第一個(gè)連接請(qǐng)求報(bào)文段并沒有丟失,而是在某個(gè)網(wǎng)絡(luò)結(jié)點(diǎn)長(zhǎng)時(shí)間的滯留了,以致延誤到連接釋放以后的某個(gè)時(shí)間才到達(dá)server。

這是一個(gè)早已失效的報(bào)文段。但Server收到此失效的連接請(qǐng)求報(bào)文段后,就誤認(rèn)為是Client再次發(fā)出的一個(gè)新的連接請(qǐng)求。

于是就向Client發(fā)出確認(rèn)報(bào)文段,同意建立連接。

假設(shè)不采用“三次握手”:只要Server發(fā)出確認(rèn),新的連接就建立了。

由于現(xiàn)在Client并沒有發(fā)出建立連接的請(qǐng)求,因此不會(huì)向Server發(fā)送數(shù)據(jù)。

但Server卻以為新的運(yùn)輸連接已經(jīng)建立,并一直等待Client發(fā)來數(shù)據(jù)。>- 這樣,Server的資源就白白浪費(fèi)掉了。

采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生:

Client不會(huì)向Server的確認(rèn)發(fā)出確認(rèn)

Server由于收不到確認(rèn),就知道Client并沒有要求建立連接

所以Server不會(huì)等待Client發(fā)送數(shù)據(jù),資源就沒有被浪費(fèi)

TCP釋放連接
TCP釋放連接需要四次揮手過程,現(xiàn)在假設(shè)A主動(dòng)釋放連接:(數(shù)據(jù)傳輸結(jié)束后,通信的雙方都可釋放連接)

第一次揮手:A發(fā)送釋放信息到B;(發(fā)出去之后,A->B發(fā)送數(shù)據(jù)這條路徑就斷了)

第二次揮手:B收到A的釋放信息之后,回復(fù)確認(rèn)釋放的信息:我同意你的釋放連接請(qǐng)求

第三次揮手:B發(fā)送“請(qǐng)求釋放連接“信息給A

第四次揮手:A收到B發(fā)送的信息后向B發(fā)送確認(rèn)釋放信息:我同意你的釋放連接請(qǐng)求

> B收到確認(rèn)信息后就會(huì)正式關(guān)閉連接;
> A等待2MSL后依然沒有收到回復(fù),則證明B端已正常關(guān)閉,于是A關(guān)閉連接

為什么TCP釋放連接需要四次揮手?

為了保證雙方都能通知對(duì)方“需要釋放連接”,即在釋放連接后都無法接收或發(fā)送消息給對(duì)方

需要明確的是:TCP是全雙工模式,這意味著是雙向都可以發(fā)送、接收的

釋放連接的定義是:雙方都無法接收或發(fā)送消息給對(duì)方,是雙向的

當(dāng)主機(jī)1發(fā)出“釋放連接請(qǐng)求”(FIN報(bào)文段)時(shí),只是表示主機(jī)1已經(jīng)沒有數(shù)據(jù)要發(fā)送 / 數(shù)據(jù)已經(jīng)全部發(fā)送完畢;

> 但是,這個(gè)時(shí)候主機(jī)1還是可以接受來自主機(jī)2的數(shù)據(jù)。

當(dāng)主機(jī)2返回“確認(rèn)釋放連接”信息(ACK報(bào)文段)時(shí),表示它已經(jīng)知道主機(jī)1沒有數(shù)據(jù)發(fā)送了

> 但此時(shí)主機(jī)2還是可以發(fā)送數(shù)據(jù)給主機(jī)1

當(dāng)主機(jī)2也發(fā)送了FIN報(bào)文段時(shí),即告訴主機(jī)1我也沒有數(shù)據(jù)要發(fā)送了

> 此時(shí),主機(jī)1和2已經(jīng)無法進(jìn)行通信:主機(jī)1無法發(fā)送數(shù)據(jù)給主機(jī)2,主機(jī)2也無法發(fā)送數(shù)據(jù)給主機(jī)1,此時(shí),TCP的連接才算釋放

1.5 UDP協(xié)議

定義:User Datagram Protocol,即用戶數(shù)據(jù)報(bào)協(xié)議,是一種傳輸層通信協(xié)議。

基于UDP的應(yīng)用層協(xié)議有TFTP、SNMP與DNS。

特點(diǎn):無連接的、不可靠的、面向報(bào)文、沒有擁塞控制

無連接的:和TCP要建立連接不同,UDP傳輸數(shù)據(jù)不需要建立連接,就像寫信,在信封寫上收信人名稱、地址就可以交給郵局發(fā)送了,至于能不能送到,就要看郵局的送信能力和送信過程的困難程度了。

不可靠的:因?yàn)閁DP發(fā)出去的數(shù)據(jù)包發(fā)出去就不管了,不管它會(huì)不會(huì)到達(dá),所以很可能會(huì)出現(xiàn)丟包現(xiàn)象,使傳輸?shù)臄?shù)據(jù)出錯(cuò)。

面向報(bào)文:數(shù)據(jù)報(bào)文,就相當(dāng)于一個(gè)數(shù)據(jù)包,應(yīng)用層交給UDP多大的數(shù)據(jù)包,UDP就照樣發(fā)送,不會(huì)像TCP那樣拆分。

沒有擁塞控制:擁塞,是指到達(dá)通信子網(wǎng)中某一部分的分組數(shù)量過多,使得該部分網(wǎng)絡(luò)來不及處理,以致引起這部分乃至整個(gè)網(wǎng)絡(luò)性能下降的現(xiàn)象,嚴(yán)重時(shí)甚至?xí)?dǎo)致網(wǎng)絡(luò)通信業(yè)務(wù)陷入停頓,即出現(xiàn)死鎖現(xiàn)象,就像交通堵塞一樣。TCP建立連接后如果發(fā)送的數(shù)據(jù)因?yàn)樾诺蕾|(zhì)量的原因不能到達(dá)目的地,它會(huì)不斷重發(fā),有可能導(dǎo)致越來越塞,所以需要一個(gè)復(fù)雜的原理來控制擁塞。而UDP就沒有這個(gè)煩惱,發(fā)出去就不管了。

應(yīng)用場(chǎng)景
很多的實(shí)時(shí)應(yīng)用(如IP電話、實(shí)時(shí)視頻會(huì)議、某些多人同時(shí)在線游戲等)要求源主機(jī)以很定的速率發(fā)送數(shù)據(jù),并且允許在網(wǎng)絡(luò)發(fā)生擁塞時(shí)候丟失一些數(shù)據(jù),但是要求不能有太大的延時(shí),UDP就剛好適合這種要求。所以說,只有不適合的技術(shù),沒有真正沒用的技術(shù)。

1.6 HTTP協(xié)議

詳情請(qǐng)看我寫的另外一篇文章你需要了解的HTTP知識(shí)都在這里了!

*

2. Socket定義

即套接字,是一個(gè)對(duì) TCP / IP協(xié)議進(jìn)行封裝 的編程調(diào)用接口(API)

> 1.  即通過`Socket`,我們才能在Andorid平臺(tái)上通過 `TCP/IP`協(xié)議進(jìn)行開發(fā)
> 2.  `Socket`不是一種協(xié)議,而是一個(gè)編程調(diào)用接口(`API`),屬于傳輸層(主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸)

成對(duì)出現(xiàn),一對(duì)套接字:

Socket ={(IP地址1:PORT端口號(hào)),(IP地址2:PORT端口號(hào))}
3. 原理

Socket的使用類型主要有兩種:

流套接字(streamsocket) :基于 TCP協(xié)議,采用 流的方式 提供可靠的字節(jié)流服務(wù)

數(shù)據(jù)報(bào)套接字(datagramsocket):基于 UDP協(xié)議,采用 數(shù)據(jù)報(bào)文 提供數(shù)據(jù)打包發(fā)送的服務(wù)

具體原理圖如下:

4. Socket 與 Http 對(duì)比

Socket屬于傳輸層,因?yàn)?TCP / IP協(xié)議屬于傳輸層,解決的是數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸?shù)膯栴}

HTTP協(xié)議 屬于 應(yīng)用層,解決的是如何包裝數(shù)據(jù)

由于二者不屬于同一層面,所以本來是沒有可比性的。但隨著發(fā)展,默認(rèn)的Http里封裝了下面幾層的使用,所以才會(huì)出現(xiàn)Socket & HTTP協(xié)議的對(duì)比:(主要是工作方式的不同):

Http:采用 請(qǐng)求—響應(yīng) 方式。

> 1.  即建立網(wǎng)絡(luò)連接后,當(dāng) 客戶端 向 服務(wù)器 發(fā)送請(qǐng)求后,服務(wù)器端才能向客戶端返回?cái)?shù)據(jù)。
> 2.  可理解為:**是客戶端有需要才進(jìn)行通信**

Socket:采用 服務(wù)器主動(dòng)發(fā)送數(shù)據(jù) 的方式

> 1.  即建立網(wǎng)絡(luò)連接后,服務(wù)器可主動(dòng)發(fā)送消息給客戶端,而不需要由客戶端向服務(wù)器發(fā)送請(qǐng)求
> 2.  可理解為:**是服務(wù)器端有需要才進(jìn)行通信**

5. 使用步驟

Socket可基于TCP或者UDP協(xié)議,但TCP更加常用

所以下面的使用步驟 & 實(shí)例的Socket將基于TCP協(xié)議

// 步驟1:創(chuàng)建客戶端 & 服務(wù)器的連接

    // 創(chuàng)建Socket對(duì)象 & 指定服務(wù)端的IP及端口號(hào) 
    Socket socket = new Socket("192.168.1.32", 1989);  

    // 判斷客戶端和服務(wù)器是否連接成功  
    socket.isConnected());

// 步驟2:客戶端 & 服務(wù)器 通信
// 通信包括:客戶端 接收服務(wù)器的數(shù)據(jù) & 發(fā)送數(shù)據(jù) 到 服務(wù)器

    <-- 操作1:接收服務(wù)器的數(shù)據(jù) -->

            // 步驟1:創(chuàng)建輸入流對(duì)象InputStream
            InputStream is = socket.getInputStream() 

            // 步驟2:創(chuàng)建輸入流讀取器對(duì)象 并傳入輸入流對(duì)象
            // 該對(duì)象作用:獲取服務(wù)器返回的數(shù)據(jù)
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);

            // 步驟3:通過輸入流讀取器對(duì)象 接收服務(wù)器發(fā)送過來的數(shù)據(jù)
            br.readLine();

    <-- 操作2:發(fā)送數(shù)據(jù) 到 服務(wù)器 -->                  

            // 步驟1:從Socket 獲得輸出流對(duì)象OutputStream
            // 該對(duì)象作用:發(fā)送數(shù)據(jù)
            OutputStream outputStream = socket.getOutputStream(); 

            // 步驟2:寫入需要發(fā)送的數(shù)據(jù)到輸出流對(duì)象中
            outputStream.write(("Carson_Ho"+"
").getBytes("utf-8"));
            // 特別注意:數(shù)據(jù)的結(jié)尾加上換行符才可讓服務(wù)器端的readline()停止阻塞

            // 步驟3:發(fā)送數(shù)據(jù)到服務(wù)端 
            outputStream.flush();  

// 步驟3:斷開客戶端 & 服務(wù)器 連接

             os.close();
            // 斷開 客戶端發(fā)送到服務(wù)器 的連接,即關(guān)閉輸出流對(duì)象OutputStream

            br.close();
            // 斷開 服務(wù)器發(fā)送到客戶端 的連接,即關(guān)閉輸入流讀取器對(duì)象BufferedReader

            socket.close();
            // 最終關(guān)閉整個(gè)Socket連接
6. 具體實(shí)例

實(shí)例 Demo 代碼包括:客戶端 & 服務(wù)器

本文著重講解客戶端,服務(wù)器僅采用最簡(jiǎn)單的寫法進(jìn)行展示

6.1 客戶端 實(shí)現(xiàn)

步驟1:加入網(wǎng)絡(luò)權(quán)限

步驟2:主布局界面設(shè)置

包括創(chuàng)建Socket連接、客戶端 & 服務(wù)器通信的按鈕

    

步驟3:創(chuàng)建Socket連接、客戶端 & 服務(wù)器通信

具體請(qǐng)看注釋

MainActivity.java

package scut.carson_ho.socket_carson;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    /**
     * 主 變量
     */

    // 主線程Handler
    // 用于將從服務(wù)器獲取的消息顯示出來
    private Handler mMainHandler;

    // Socket變量
    private Socket socket;

    // 線程池
    // 為了方便展示,此處直接采用線程池進(jìn)行線程管理,而沒有一個(gè)個(gè)開線程
    private ExecutorService mThreadPool;

    /**
     * 接收服務(wù)器消息 變量
     */
    // 輸入流對(duì)象
    InputStream is;

    // 輸入流讀取器對(duì)象
    InputStreamReader isr ;
    BufferedReader br ;

    // 接收服務(wù)器發(fā)送過來的消息
    String response;

    /**
     * 發(fā)送消息到服務(wù)器 變量
     */
    // 輸出流對(duì)象
    OutputStream outputStream;

    /**
     * 按鈕 變量
     */

    // 連接 斷開連接 發(fā)送數(shù)據(jù)到服務(wù)器 的按鈕變量
    private Button btnConnect, btnDisconnect, btnSend;

    // 顯示接收服務(wù)器消息 按鈕
    private TextView Receive,receive_message;

    // 輸入需要發(fā)送的消息 輸入框
    private EditText mEdit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**
         * 初始化操作
         */

        // 初始化所有按鈕
        btnConnect = (Button) findViewById(R.id.connect);
        btnDisconnect = (Button) findViewById(R.id.disconnect);
        btnSend = (Button) findViewById(R.id.send);
        mEdit = (EditText) findViewById(R.id.edit);
        receive_message = (TextView) findViewById(R.id.receive_message);
        Receive = (Button) findViewById(R.id.Receive);

        // 初始化線程池
        mThreadPool = Executors.newCachedThreadPool();

        // 實(shí)例化主線程,用于更新接收過來的消息
        mMainHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 0:
                        receive_message.setText(response);
                        break;
                }
            }
        };

        /**
         * 創(chuàng)建客戶端 & 服務(wù)器的連接
         */
        btnConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 利用線程池直接開啟一個(gè)線程 & 執(zhí)行該線程
                mThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {

                        try {

                            // 創(chuàng)建Socket對(duì)象 & 指定服務(wù)端的IP 及 端口號(hào)
                            socket = new Socket("192.168.1.172", 8989);

                            // 判斷客戶端和服務(wù)器是否連接成功
                            System.out.println(socket.isConnected());

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

                    }
                });

            }
        });

        /**
         * 接收 服務(wù)器消息
         */
        Receive.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 利用線程池直接開啟一個(gè)線程 & 執(zhí)行該線程
                mThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {

                          try {
                            // 步驟1:創(chuàng)建輸入流對(duì)象InputStream
                            is = socket.getInputStream();

                              // 步驟2:創(chuàng)建輸入流讀取器對(duì)象 并傳入輸入流對(duì)象
                              // 該對(duì)象作用:獲取服務(wù)器返回的數(shù)據(jù)
                              isr = new InputStreamReader(is);
                              br = new BufferedReader(isr);

                              // 步驟3:通過輸入流讀取器對(duì)象 接收服務(wù)器發(fā)送過來的數(shù)據(jù)
                              response = br.readLine();

                              // 步驟4:通知主線程,將接收的消息顯示到界面
                              Message msg = Message.obtain();
                              msg.what = 0;
                              mMainHandler.sendMessage(msg);

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

                    }
                });

            }
        });

        /**
         * 發(fā)送消息 給 服務(wù)器
         */
        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 利用線程池直接開啟一個(gè)線程 & 執(zhí)行該線程
                mThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {

                        try {
                            // 步驟1:從Socket 獲得輸出流對(duì)象OutputStream
                            // 該對(duì)象作用:發(fā)送數(shù)據(jù)
                            outputStream = socket.getOutputStream();

                            // 步驟2:寫入需要發(fā)送的數(shù)據(jù)到輸出流對(duì)象中
                            outputStream.write((mEdit.getText().toString()+"
").getBytes("utf-8"));
                            // 特別注意:數(shù)據(jù)的結(jié)尾加上換行符才可讓服務(wù)器端的readline()停止阻塞

                            // 步驟3:發(fā)送數(shù)據(jù)到服務(wù)端
                            outputStream.flush();

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

                    }
                });

            }
        });

        /**
         * 斷開客戶端 & 服務(wù)器的連接
         */
        btnDisconnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                try {
                    // 斷開 客戶端發(fā)送到服務(wù)器 的連接,即關(guān)閉輸出流對(duì)象OutputStream
                    outputStream.close();

                    // 斷開 服務(wù)器發(fā)送到客戶端 的連接,即關(guān)閉輸入流讀取器對(duì)象BufferedReader
                    br.close();

                    // 最終關(guān)閉整個(gè)Socket連接
                    socket.close();

                    // 判斷客戶端和服務(wù)器是否已經(jīng)斷開連接
                    System.out.println(socket.isConnected());

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

            }
        });

    }
}
6.2 服務(wù)器 實(shí)現(xiàn)

因本文主要講解客戶端,所以服務(wù)器僅僅是為了配合客戶端展示;

為了簡(jiǎn)化服務(wù)器使用,此處采用Mina框架

> 1.  服務(wù)器代碼請(qǐng)?jiān)赻eclipse`平臺(tái)運(yùn)行
> 2.  按照我的步驟一步步實(shí)現(xiàn)就可以無腦運(yùn)行了

步驟1:導(dǎo)入Mina

請(qǐng)直接移步到百度網(wǎng)盤:下載鏈接(密碼: q73e)

步驟2:創(chuàng)建服務(wù)器線程
TestHandler.java

package mina;
// 導(dǎo)入包

public class TestHandler extends IoHandlerAdapter {

    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        System.out.println("exceptionCaught: " + cause);
    }

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        System.out.println("recieve : " + (String) message);
        session.write("hello I am server");
    }

    @Override
    public void messageSent(IoSession session, Object message) throws Exception {

    }

    @Override
    public void sessionClosed(IoSession session) throws Exception {
        System.out.println("sessionClosed");
    }

    @Override
    public void sessionOpened(IoSession session) throws Exception {
        System.out.println("sessionOpen");
    }

    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
    }

}

步驟3:創(chuàng)建服務(wù)器主代碼
TestHandler.java

package mina;

import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class TestServer {
    public static void main(String[] args) {
        NioSocketAcceptor acceptor = null;
        try {
            acceptor = new NioSocketAcceptor();
            acceptor.setHandler(new TestHandler());
            acceptor.getFilterChain().addLast("mFilter", new ProtocolCodecFilter(new TextLineCodecFactory()));
            acceptor.setReuseAddress(true);
            acceptor.bind(new InetSocketAddress(8989));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

至此,客戶端 & 服務(wù)器的代碼均實(shí)現(xiàn)完畢。

6.3 測(cè)試結(jié)果

點(diǎn)擊 Connect按鈕: 連接成功

輸入發(fā)送的消息,點(diǎn)擊 Send 按鈕發(fā)送

服務(wù)器接收到客戶端發(fā)送的消息

點(diǎn)擊 Receive From Message按鈕,客戶端 讀取 服務(wù)器返回的消息

點(diǎn)擊 DisConnect按鈕,斷開 客戶端 & 服務(wù)器的連接

6.4 源碼地址

Socket具體實(shí)例

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/70564.html

相關(guān)文章

  • 好文章必讀 - 收藏集 - 掘金

    摘要:方法即為收集器,它接收高階函數(shù)和的后端掘金年的第一天,我坐在獨(dú)墅湖邊,寫下這篇文章。正因如此,所以最全系列教程后端掘金是從版本開始引入的一個(gè)新的,可以替代標(biāo)準(zhǔn)的。 設(shè)計(jì)模式之單例模式 - 掘金前言 作為一個(gè)好學(xué)習(xí)的程序開發(fā)者,應(yīng)該會(huì)去學(xué)習(xí)優(yōu)秀的開源框架,當(dāng)然學(xué)習(xí)的過程中不免會(huì)去閱讀源碼,這也是一個(gè)優(yōu)秀程序員的必備素養(yǎng),在學(xué)習(xí)的過程中很多人會(huì)遇到的障礙,那就是設(shè)計(jì)模式。很多優(yōu)秀的框架會(huì)運(yùn)...

    FrozenMap 評(píng)論0 收藏0
  • 如何自學(xué)Android

    摘要:如何自學(xué)知識(shí)儲(chǔ)備本知識(shí)點(diǎn)不做重點(diǎn)講解對(duì)于有基礎(chǔ)的同學(xué)推薦看編程思想,鞏固基礎(chǔ),查漏補(bǔ)全,了解并熟悉更多細(xì)節(jié)知識(shí)點(diǎn)?;A(chǔ)學(xué)習(xí)基礎(chǔ)學(xué)習(xí)對(duì)于這些基礎(chǔ)的使用谷歌官網(wǎng)給出了很好的實(shí)例。是谷歌根據(jù)自帶的改進(jìn)的。是基于谷歌內(nèi)核的一個(gè)可以作為瀏覽器的視圖。 如何自學(xué)Android 1. Java知識(shí)儲(chǔ)備 本知識(shí)點(diǎn)不做重點(diǎn)講解: 對(duì)于有基礎(chǔ)的同學(xué)推薦看《Java編程思想》,鞏固基礎(chǔ),查漏補(bǔ)全,了解...

    alexnevsky 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<