国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

The question / 2411人閱讀

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

前言

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

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

目錄

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

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

其中:

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

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

1.2 端口號(PORT)

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

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

> 我們不可以亂用

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

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

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

在Socket使用時,可以用1024~65535的端口號

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

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

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

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

如圖:

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

1.4 TCP協(xié)議

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

答:防止服務(wù)器端因為接收了早已失效的連接請求報文從而一直等待客戶端請求,從而浪費資源

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1.5 UDP協(xié)議

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

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

特點:無連接的、不可靠的、面向報文、沒有擁塞控制

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

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

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

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

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

1.6 HTTP協(xié)議

詳情請看我寫的另外一篇文章你需要了解的HTTP知識都在這里了!

*

2. Socket定義

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

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

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

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

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

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

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

具體原理圖如下:

4. Socket 與 Http 對比

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

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

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

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

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

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

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

5. 使用步驟

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

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

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

    // 創(chuàng)建Socket對象 & 指定服務(wù)端的IP及端口號 
    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)建輸入流對象InputStream
            InputStream is = socket.getInputStream() 

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

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

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

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

            // 步驟2:寫入需要發(fā)送的數(shù)據(jù)到輸出流對象中
            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)閉輸出流對象OutputStream

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

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

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

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

6.1 客戶端 實現(xiàn)

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

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

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

    

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

具體請看注釋

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)行線程管理,而沒有一個個開線程
    private ExecutorService mThreadPool;

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

    // 輸入流讀取器對象
    InputStreamReader isr ;
    BufferedReader br ;

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

    /**
     * 發(fā)送消息到服務(wù)器 變量
     */
    // 輸出流對象
    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();

        // 實例化主線程,用于更新接收過來的消息
        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) {

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

                        try {

                            // 創(chuàng)建Socket對象 & 指定服務(wù)端的IP 及 端口號
                            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) {

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

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

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

                              // 步驟3:通過輸入流讀取器對象 接收服務(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) {

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

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

                            // 步驟2:寫入需要發(fā)送的數(shù)據(jù)到輸出流對象中
                            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)閉輸出流對象OutputStream
                    outputStream.close();

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

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

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

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

            }
        });

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

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

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

> 1.  服務(wù)器代碼請在`eclipse`平臺運行
> 2.  按照我的步驟一步步實現(xiàn)就可以無腦運行了

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

請直接移步到百度網(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ù)器的代碼均實現(xiàn)完畢。

6.3 測試結(jié)果

點擊 Connect按鈕: 連接成功

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

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

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

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

6.4 源碼地址

Socket具體實例

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/70564.html

相關(guān)文章

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

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

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

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

    alexnevsky 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<