Android 開發: 通信篇-TCP客戶端


 

 

 

 

說明

 

這節教給大家用Android寫一個TCP客戶端程序

官方文檔

https://www.android-doc.com/reference/java/net/Socket.html

 

頁面

 

 

 

編寫連接程序

1.獲取控件

 

 

 

    EditText editTextIPAddress,editTextPort;//輸入IP地址,端口號
    Button buttonConnect;//連接按鈕

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

        buttonConnect = findViewById(R.id.buttonConnect);
        editTextIPAddress = findViewById(R.id.editTextIPAddress);
        editTextPort = findViewById(R.id.editTextPort);


    }

 

 

2.添加網絡權限

<uses-permission android:name="android.permission.INTERNET" />

 

 

 

 

 

3.定義一個socket

 

 

 

Socket socket;

 

 

4.編寫按鈕點擊連接/斷開程序

 

 

 

 

MyHandler myHandler;//使用Handler更新控件

myHandler = new MyHandler();

 

 

 

 

        buttonConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (buttonConnect.getText()=="連接"){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            try{
                                socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));
                                if(socket.isConnected()){
                                    msg.what = 1;//設置消息變量的 what 變量值 為1
                                }
                            }catch (Exception e){
                                msg.what = 0;//設置消息變量的 what 變量值 為0
                            }
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                    }).start();
                }
                else{
                    try{ socket.close(); }catch (Exception e){} //關閉連接
                    buttonConnect.setText("連接");//按鈕顯示連接
                }
            }
        });

 

 

 

 

//Handler
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 0:
                    Toast.makeText(MainActivity.this,"連接出錯",Toast.LENGTH_SHORT).show();
                    break;
                case 1:
                    buttonConnect.setText("斷開");//按鈕顯示斷開
                    break;
                default: break;
            }
        }
    }

 

 

提示:獲取IP地址和端口號,執行連接

socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));

 

 

 

 

 

當前程序

    EditText editTextIPAddress,editTextPort;//輸入IP地址,端口號
    Button buttonConnect;//連接按鈕
    Socket socket;

    MyHandler myHandler;//使用Handler更新控件
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHandler = new MyHandler();
        buttonConnect = findViewById(R.id.buttonConnect);
        buttonConnect.setText("連接");
        editTextIPAddress = findViewById(R.id.editTextIPAddress);
        editTextPort = findViewById(R.id.editTextPort);

        buttonConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (buttonConnect.getText()=="連接"){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            try{
                                socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));
                                if(socket.isConnected()){
                                    msg.what = 1;//設置消息變量的 what 變量值 為1
                                }
                            }catch (Exception e){
                                msg.what = 0;//設置消息變量的 what 變量值 為0
                            }
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                    }).start();
                }
                else{
                    try{ socket.close(); }catch (Exception e){} //關閉連接
                    buttonConnect.setText("連接");//按鈕顯示連接
                }
            }
        });
    }

    //Handler
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 0:
                    Toast.makeText(MainActivity.this,"連接出錯",Toast.LENGTH_SHORT).show();
                    break;
                case 1:
                    buttonConnect.setText("斷開");//按鈕顯示斷開
                    break;
                default: break;
            }
        }
    }

 

接收數據

 

 

 

1.定義 InputStream 用於獲取數據輸入流,定義一個數組用於緩存數據

 

 

 

    InputStream inputStream;//獲取輸入流
    byte[] RevBuff = new byte[1460];//緩存數據

 

 

 

2.定義一個函數,里面放一個任務,用於不停的接收數據

 

 

 

 

 

public void Recv(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (socket!= null && socket.isConnected()){
                    try{
                        int Len = inputStream.read(RevBuff);//獲取數據
                        if(Len!=-1){
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 3;//設置消息變量的 what 變量值 為3
                            msg.arg1 = Len;//接收的數據個數
                            msg.obj = RevBuff;//傳遞數據
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                        else{//連接異常斷開
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 0;//設置消息變量的 what 變量值 為0
                            myHandler.sendMessage(msg);//插入消息隊列
                            break;
                        }
                    }catch (Exception e){//連接異常斷開
                        Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                        msg.what = 0;//設置消息變量的 what 變量值 為0
                        myHandler.sendMessage(msg);//插入消息隊列
                        break;
                    }
                }
            }
        }).start();
    }

 

 

 

3.調用接收函數

 

 

 

 

4.在Handle中處理數據,把數據顯示在頁面

4.1.獲取控件

 

 

 

 

 

 

 

4.2.把接收的消息追加到Textview顯示

 

 

測試

1.電腦端開啟TCP服務器

 

 

 

 

 

2.保證手機和電腦在一個局域網內

查看自己的電腦IP

 

 

 

 

 

3.手機連接

 

 

 

 

 

 

 

 

 

 

接收顯示16進制數據

1.關於16進制顯示和前面的串口上位機顯示16進制數據是一樣的道理

https://www.cnblogs.com/yangfengwu/p/12382103.html

 

 

 

 

2.JAVA和C#提供的函數不一樣,java的轉換程序如下:

 

    /**
     * 16進制byte轉16進制String--用空格隔開
     * @param bytes
     * @return
     */
    public static String byteToHexStr(byte[] bytes)
    {    
        String str_msg = "";
        for (int i = 0; i < bytes.length; i++){    
            str_msg = str_msg + String.format("%02X",bytes[i])+" ";
        }    
        return str_msg;    
    }  

 

 

3.獲取16進制選擇控件

 

 

 

 

4.編寫處理函數

 

 

 

 

 

 

 

 

測試

 

 

 

 

 

 

 

清除接收

 

 

發送數據

1.獲取控件,定義輸出流變量

 

 

 

 

2.獲取輸出流

 

 

 

 

3.點擊發送按鈕發送發送文本框里面的數據

 

 

 

 

4.測試

 

 

 

 

 

 

發送16進制數據

1.文本框里面輸入的是字符串

假設輸入的是 55FD

那么獲取的是 "55FD"

需要轉換為 0x55  0xFD

 

獲取第一個字符 5    hexString.charAt(0)

 

轉換為 16進制形式  Character.digit(hexString.charAt(0), 16)

 

獲取第二個字符5     hexString.charAt(1)

轉換為 16進制形式  Character.digit(hexString.charAt(1), 16)

 

然后組合成一個16進制

byte data =  (byte) ((Character.digit(hexString.charAt(0), 16) << 4) + Character.digit(hexString.charAt(1), 16))

 

 

2.完整的程序如下

 

/***
     *"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,0xD9}
     * @param hexString
     * @return
     */
    public static byte[] hexStringToByteArray(String hexString) {
        StringBuilder sb = null;
        hexString = hexString.replaceAll(" ", "");

        if ((hexString.length()%2)!=0) {//數據不是偶數
            sb = new StringBuilder(hexString);//構造一個StringBuilder對象
            sb.insert(hexString.length()-1, "0");//插入指定的字符串
            hexString = sb.toString();
        }

        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            if ((
                    (hexString.charAt(i)>='0' && hexString.charAt(i)<='9') ||
                    (hexString.charAt(i)>='A' && hexString.charAt(i)<='F') ||
                    (hexString.charAt(i)>='a' && hexString.charAt(i)<='f')
             )&&
                    (hexString.charAt(i+1)>='0' && hexString.charAt(i+1)<='9') ||
                    (hexString.charAt(i+1)>='A' && hexString.charAt(i+1)<='F') ||
                    (hexString.charAt(i+1)>='a' && hexString.charAt(i+1)<='f')){
                // 兩位一組,表示一個字節,把這樣表示的16進制字符串,還原成一個字節
                bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
                        .digit(hexString.charAt(i+1), 16));
            }
            else return null;
        }
        return bytes;
    }

 

 

 

 

3.獲取控件

 

 

 

 

 

4.編寫處理程序

 

 

 

 

 

5.測試

 

 

 

 

 

 

補充

讓輸入的內容默認顯示在左上角

 

 

 

 

 

 

 

 

android:gravity="top"

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM