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

資訊專欄INFORMATION COLUMN

初窺Socket:與自己聊次天

Y3G / 3285人閱讀

摘要:什么是網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)。通常用來實(shí)現(xiàn)客戶方和服務(wù)方的連接。

什么是Socket

網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)Socket。Socket通常用來實(shí)現(xiàn)客戶方和服務(wù)方的連接。Socket是TCP/IP協(xié)議的一個(gè)十分流行的編程界面,一個(gè)Socket由一個(gè)IP地址和一個(gè)端口號唯一確定

但是,Socket所支持的協(xié)議種類不僅TCP/IP一種,因此兩者之間是沒有必然聯(lián)系的。在Java環(huán)境下,Socket編程主要是指基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程

PS:雖然湊字?jǐn)?shù)這種技能早就點(diǎn)滿了,但關(guān)于更多Socket及TCP/IP相關(guān)概念,還請各位看官自行/先行了解,這里不再多做贅述

本次Demo預(yù)覽

工具準(zhǔn)備

Eclipse(若你沒有Eclipse也沒事兒,后邊告訴你用命令行編譯運(yùn)行?。?/p>

AndroidStudio(若你本身就是用Eclipse開發(fā)安卓程序,那Eclipse就夠了)

服務(wù)端

OK,話不多說,開干

首先在Eclipse新建一個(gè)Java項(xiàng)目,就叫SocketDemo吧

接下來咱們要監(jiān)聽是否有客戶端發(fā)送連接請求,如果有,則連接并處理

SocketDemo.java:

public class SocketDemo {
    /**
     * 端口號 注意:0~1023為系統(tǒng)所保留端口號,選擇端口號時(shí)應(yīng)大于1023,具體隨便你取
     */
    public static int PORT = 2345;

    public static void main(String[] args) {
        try {
            //serverSocket用于監(jiān)聽是否有客戶端發(fā)送連接請求
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("服務(wù)啟動...");
            //serverSocket.accept():如果有客戶端發(fā)送連接請求,
            //則返回一個(gè)socket供處理與客戶端的連接,否則一直阻塞監(jiān)聽
            Socket socket = serverSocket.accept();
            System.out.println("與客戶端連接成功...");
            //這個(gè)MySocket是啥呢?是一個(gè)對socket的封裝,方便操作
            MySocket mySocket = new MySocket(socket);
            //由于MySocket繼承于Thread,所以需要start()一下
            //致于為啥要繼承于Thread來封裝socket,請看下方 MySocket類
            mySocket.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注釋中的兩個(gè)問題,很好理解,不多說,直接看看MySocket是怎么寫的吧:

MySocket.java

public class MySocket extends Thread {
    Socket mSocket;
    BufferedWriter mWriter;
    BufferedReader mReader;

    public MySocket(Socket socket) {
        this.mSocket = socket;
        try {
            mWriter = new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream(), "utf-8"));
            mReader = new BufferedReader(new InputStreamReader(
                        socket.getInputStream(), "utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
    * 向客戶端發(fā)送消息
    * msg 發(fā)送消息內(nèi)容
    **/
    public void send(String msg) {
        try {
            // 客戶端按行(readLine)讀取消息,所以每條消息最后必須加換行符 
,否則讀取不到
            mWriter.write(msg + "
");
            mWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
    * 
    * 不斷讀取來自客戶端的消息,一旦收到消息,則自動回復(fù)
    **/
    @Override
    public void run() {
        super.run();
        try {
            String line;
            //服務(wù)端按行讀取消息
            //不斷按行讀取,獲得來自客戶端的消息
            while ((line = mReader.readLine()) != null) {
                System.out.println("客戶端消息:" + line);
                //收到客戶端消息后,自動回復(fù)
                send("已經(jīng)收到你發(fā)送的"" + line + """);
            }
            mReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }
}

看完MySocket之后豁然開朗,原來將讀取客戶端消息的操作是阻塞的,要放在子線程來做,所以繼承于Thread會方便一點(diǎn)

那么至此,服務(wù)端的程序已經(jīng)寫完了

什么?你問怎么這么簡單?!原因有兩個(gè):

這只是一個(gè)基礎(chǔ)的Socket服務(wù)端程序,不用考慮那么多其他情況,自然幾行代碼就搞定了

沒錯(cuò),Socket就是這么簡單!

接下來你會發(fā)現(xiàn),客戶端特么更簡單!

客戶端(Android)

第一步新建一個(gè)安卓項(xiàng)目,也叫SocketDemo吧,畢竟,湊字?jǐn)?shù)這個(gè)技能我比較熟練

簡單一點(diǎn),布局中就一個(gè)按鈕(id=btn_send),用來發(fā)送消息,初窺嘛,簡單就是王道,布局代碼就不上了

接下來看看MainActivity的代碼:

不行,在看MainActivity之前還有一些話要交代清楚:

如果你將安卓程序跑在電腦的虛擬機(jī)上,則你訪問的IP地址為:10.0.2.2(虛擬機(jī)只能通過這個(gè)IP訪問電腦)

如果你將安卓程序跑在真機(jī)上,那么你需要在CMD中輸入ipconfig獲取到IPv4地址,并且確保手機(jī)和電腦在同一個(gè)網(wǎng)絡(luò)下(連接了同一個(gè)WIFI)

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        connectServer();
        findViewById(R.id.btn_send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendMsg("2333");
            }
        });
    }

    private Socket mSocket;
    private BufferedWriter mWriter;
    private BufferedReader mReader;
    //這個(gè)IP上面解釋過了噢,要理解一下
    private static String IP = "10.0.2.2";
    //切記端口號一定要和服務(wù)端保持一致!
    private static int PORT = 2345;

    private void connectServer() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mSocket = new Socket(IP, PORT);
                    mWriter = new BufferedWriter(new OutputStreamWriter(
                            mSocket.getOutputStream(), "utf-8"));
                    mReader = new BufferedReader(new InputStreamReader(
                            mSocket.getInputStream(), "utf-8"));
                    Log.i(TAG, "連接服務(wù)端成功");
                } catch (IOException e) {
                    Log.i(TAG, "連接服務(wù)端失敗");
                    e.printStackTrace();
                    return;
                }

                try {
                    String line;
                    while ((line = mReader.readLine()) != null) {
                        Log.i(TAG, "服務(wù)端消息: " + line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.i(TAG, "服務(wù)端:已停止服務(wù)");
                }
            }
        }).start();
    }

    private void sendMsg(String msg) {
        // 如果mSocket為null有可能兩種情況:
        // 1.還在嘗試連接服務(wù)端
        // 2.連接失敗
        if (mSocket == null){
            Toast.makeText(this,"連接未完成或連接失敗,無法發(fā)送消息!",Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            //服務(wù)端是按行讀取消息,所以每條消息最后必須加換行符 

            mWriter.write(msg + "
");
            mWriter.flush();
        } catch (IOException e) {
            Toast.makeText(this,"發(fā)送失敗:服務(wù)端已關(guān)閉服務(wù)!",Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

}

這就寫完了客戶端??對,這就寫完了...那你別問為啥Socket咋就這么點(diǎn)內(nèi)容,Socket本來也不是啥難點(diǎn)~

并且,這只是一個(gè)非常非常基礎(chǔ)的Demo

OK,到這里就可以來跑一下程序試一試了

跑起來 跑服務(wù)端程序

如果你有Eclipse,那么直接在Eclipse內(nèi)跑起來就行了!

如果很不巧,你沒有Eclipse

新建本文章服務(wù)端部分的SocketDemo.javaMySocket.java兩個(gè)文件,并且放在同一個(gè)文件夾下,上面代碼沒有寫出import包,不能直接copy進(jìn)文件內(nèi)用,文末我會放出所有源代碼,到文末copy一下放在兩個(gè)文件內(nèi)就行了(當(dāng)然你得確保你有JDK環(huán)境!雖然作為安卓狗,這是必要的,但還是提醒一下?。?/p>

打開CMD,切換進(jìn)入上述兩個(gè)文件所在的目錄

執(zhí)行

javac *.java
java SocketDemo

就將程序跑起來了(ctrl+c退出程序)

注意事項(xiàng):

在Eclipse內(nèi)運(yùn)行的程序,切記:如果修改內(nèi)容后要重新啟動程序,請先將正在運(yùn)行的程序關(guān)閉,否則將一直占用端口!無法再以此端口再次啟用一次程序!

如果用CMD運(yùn)行的程序,提示編碼錯(cuò)誤,請將所有中文替換成英文,或者將兩個(gè).java文件內(nèi)容轉(zhuǎn)換成GBK編碼(建議換成英文!英文好的哥們兒,上!)

跑客戶端程序

直接跑安卓程序就行了!

在Eclipse跑服務(wù)端的圖已經(jīng)在文首放出,這里放一個(gè)CMD下跑服務(wù)端的圖片:

注:不知為什么發(fā)送消息的時(shí)候,命令行及LogCat不會即時(shí)顯示出內(nèi)容,在我ctrl+c退出程序之后才會一次全出來,若有知道的朋友,還望指教!萬分感謝!

改進(jìn)一個(gè)不足

想一下,服務(wù)端程序只響應(yīng)一個(gè)客戶端,如果又有客戶端發(fā)出連接請求,那豈不是無法響應(yīng)了!

再想一下覺得不對,也就是我自己測試,哪來的第二個(gè)客戶端發(fā)出連接請求

再再想一下,如果你改了一下安卓端的代碼,又一次點(diǎn)了運(yùn)行,那誰來響應(yīng)你?!這樣的話,因?yàn)樾薷陌沧慷舜a,又得去把服務(wù)端的程序停了,再啟動一下,多麻煩!

好吧,既然分析了確實(shí)有這個(gè)麻煩,那就把它解決掉:

public class SocketDemo {

    public static int PORT = 2745;

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("服務(wù)啟動...");
            //寫一個(gè)死循環(huán),如果有一個(gè)客戶端連接成功,那么繼續(xù)讓serverSocket.accept()阻塞住
            //等待下一個(gè)客戶端請求,這樣不論有多少個(gè)客戶端請求過來,都可以響應(yīng)到,
            //結(jié)束調(diào)試的時(shí)候再關(guān)閉服務(wù)端程序
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("客戶端連接成功...");
                MySocket mySocket = new MySocket(socket);
                mySocket.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

so easy~不解釋了~

至此整個(gè)SocketDemo就完成了,對Socket的第一步已經(jīng)邁出了,那么趕緊理解好,然后再深入Socket吧!

源碼

SocketDemo.java:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketDemo {

    public static int PORT = 2745;

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("服務(wù)啟動...");
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("客戶端連接成功...");
                MySocket mySocket = new MySocket(socket);
                mySocket.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

MySocket.java:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class MySocket extends Thread {
    Socket mSocket;
    BufferedWriter mWriter;
    BufferedReader mReader;

    public MySocket(Socket socket) {
        this.mSocket = socket;
        try {
            mWriter = new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream(), "utf-8"));
            mReader = new BufferedReader(new InputStreamReader(
                        socket.getInputStream(), "utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void send(String msg) {
        try {
            mWriter.write(msg + "
");
            mWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        super.run();
        try {
            String line;
            while ((line = mReader.readLine()) != null) {
                System.out.println("客戶端消息:" + line);
                send("收到:"" + line + """);
            }
            mReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }
}

客戶端(安卓端)的我就不放了!

結(jié)語

更多內(nèi)容歡迎訪問我的主頁我的博客

如果我的文章確實(shí)有幫助到你,請不要忘了點(diǎn)一下文末的"?"讓他變成"?"

作為新手難免很多地方理解不到位,文中若有錯(cuò)誤請直(bu)接(yao)指(ma)出(wo)

寫作不易!

致于題目叫"與自己聊次天",我想解釋一

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

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

相關(guān)文章

  • 初窺Socket自己次天

    摘要:什么是網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)。通常用來實(shí)現(xiàn)客戶方和服務(wù)方的連接。 什么是Socket 網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)Socket。Socket通常用來實(shí)現(xiàn)客戶方和服務(wù)方的連接。Socket是TCP/IP協(xié)議的一個(gè)十分流行的編程界面,一個(gè)Socket由一個(gè)IP地址和一個(gè)端口號唯一確...

    蘇丹 評論0 收藏0
  • 【C++】初窺門徑---入門篇

    摘要:在大型的工程中,自己定義的變量函數(shù),類名與其他人定義的相沖突等問題。使用標(biāo)準(zhǔn)輸出控制臺和標(biāo)準(zhǔn)輸入鍵盤時(shí),必須包含頭文件以及標(biāo)準(zhǔn)命名空間。缺省參數(shù)概念缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)默認(rèn)值。 目錄 前言 1.命名空間 1.1命名空間定義 1.2 命名空間使用 2. C++的輸入和...

    不知名網(wǎng)友 評論0 收藏0
  • Ubuntu 17.04 x64 安裝 Docker CE 初窺 Dockerfile 部署 Ngi

    摘要:容器運(yùn)行時(shí),會打印一條信息消息并退出。因此,更好地做法是將需要使用的用戶加入用戶組。涉及到了兩條指令,和。執(zhí)行命令指令是用來執(zhí)行命令行命令的。 Docker 是個(gè)劃時(shí)代的開源項(xiàng)目,它徹底釋放了計(jì)算虛擬化的威力,極大提高了應(yīng)用的運(yùn)行效率,降低了云計(jì)算資源供應(yīng)的成本!使用 Docker,可以讓應(yīng)用的部署、測試和分發(fā)都變得前所未有的高效和輕松! 無論是應(yīng)用開發(fā)者、運(yùn)維人員、還是其他信息技術(shù)從...

    fyber 評論0 收藏0
  • Ubuntu 17.04 x64 安裝 Docker CE 初窺 Dockerfile 部署 Ngi

    摘要:容器運(yùn)行時(shí),會打印一條信息消息并退出。因此,更好地做法是將需要使用的用戶加入用戶組。涉及到了兩條指令,和。執(zhí)行命令指令是用來執(zhí)行命令行命令的。 Docker 是個(gè)劃時(shí)代的開源項(xiàng)目,它徹底釋放了計(jì)算虛擬化的威力,極大提高了應(yīng)用的運(yùn)行效率,降低了云計(jì)算資源供應(yīng)的成本!使用 Docker,可以讓應(yīng)用的部署、測試和分發(fā)都變得前所未有的高效和輕松! 無論是應(yīng)用開發(fā)者、運(yùn)維人員、還是其他信息技術(shù)從...

    seanHai 評論0 收藏0
  • [譯]初窺Express 5

    摘要:被移除的方法和屬性被改變?yōu)閺?fù)數(shù)形式的方法名以下這些方法名被更改為了復(fù)數(shù)形式。在中,使用單數(shù)的方法名將會得到一個(gè)警告。在中,被它的駝峰命名版本所取代。在中,中會刪去端口號,而在中,端口號會被保留。 前言 Express 5.0 仍處于alpha版中,但是我們還是想先來初窺一下新的express版本中將會有哪些改變,以及如何將你的應(yīng)用從Express 4 遷移至 Express 5。 Ex...

    joywek 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<