中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android怎么使用socket進行二進制流數據傳輸

發布時間:2023-04-11 16:17:24 來源:億速云 閱讀:135 作者:iii 欄目:開發技術

本篇內容主要講解“Android怎么使用socket進行二進制流數據傳輸”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Android怎么使用socket進行二進制流數據傳輸”吧!

簡單的自定義協議

我們自定義一個簡單的通信協議,協議一共傳輸兩種信息,第一種是文字,第二種是二進制流(其實文字也可以用二進制流表示),傳輸過程如下圖所示。

Android怎么使用socket進行二進制流數據傳輸

我們定義的簡單通信協議規則如下

1.首先發送一個字節的信息(就是圖中的type),表示一段消息的開始,同時也表明了后面二進制數據的類型(文字信息還是二進制流數據)

2.每一個chunk都由三個字節的長度信息和相應的二進制流信息組成,接收方在接收到三個字節的長度信息后,繼續使用相應大小的緩沖區接收后面的流數據

3.當接收到三個字節的000的時候表示數據接收完成,接收方將二進制流數據拼接起來即可

我們規定一個最大的分段長度,一旦發送的數據超過這個分段長度就需要進行分段發送。

發送的代碼示例如下

    // 發送文件
    public void sendFile(int size) {
        new Thread(()->{
            try {
                // 表示發送文件
                outputStream.write("2".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            for(int i=0; i<size/SocketUtil.MAX_CHUNK+1; i++) {
                StringBuffer sb = new StringBuffer();
                if (i!=size / SocketUtil.MAX_CHUNK) {
                    for (int j = 0; j < SocketUtil.MAX_CHUNK; j++) {
                        sb.append('a');
                    }
                }
                else if(i==size/SocketUtil.MAX_CHUNK && size%SocketUtil.MAX_CHUNK==0) {
                    break;
                }
                else {
                    for (int j = 0; j < size % SocketUtil.MAX_CHUNK; j++) {
                        sb.append('a');
                    }
                }
                try {
                    SocketUtil.sendInfo("[客戶端]發送一個數據包,大小" + sb.toString().getBytes().length + "B");
                    // 發送chunk的長度
                    outputStream.write(SocketUtil.intToStr(sb.toString().getBytes().length).getBytes());
                    // 發送chunk塊
                    outputStream.write(sb.toString().getBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 最后發送000表示結束
            try {
                outputStream.write("000".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }

接收二進制流的代碼示例如下

    // 讀取二進制信息
    public static byte[] readBytes(InputStream inputStream, String log) {
        byte[] len = new byte[3];
        byte[] allbytes = new byte[10000];
        int idx = 0;
        try {
            inputStream.read(len);
            // 然后再根據讀取的長度信息讀取二進制流
            // 只要不是最后一個二進制流就繼續讀取
            while (SocketUtil.parseLen(len) != 0) {
                byte[] temp = new byte[SocketUtil.parseLen(len)];
                inputStream.read(temp);
                idx = SocketUtil.appendBytes(allbytes, temp, idx);
                String info = "[" + log + "]接收一個數據包,大小" + SocketUtil.parseLen(len) + "B";
                SocketUtil.sendInfo(info);
                inputStream.read(len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SocketUtil.getNewArr(allbytes, idx);
    }

其實我理解的所謂的通信協議,就是發送方和接收方都遵守的某種規則,按照這種規則發送和接收數據就可以保證數據的完整性。

完整的代碼

這段代碼只有四個java文件,非常簡單,只是一個極簡的通信協議模型。

Android怎么使用socket進行二進制流數據傳輸

首先來看一下界面定義

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <EditText
        android:id="@+id/text_file_size"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入待發送文件大小"/>
    <Button
        android:id="@+id/button_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="發送文件"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="消息欄:"/>
    <TextView
        android:id="@+id/text_info"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

然后是MainActivity

public class MainActivity extends AppCompatActivity {
    private EditText text_file_size;
    private Button button_send;
    private TextView text_info;
    private BroadcastReceiver broadcastReceiver;
    private SocketClient socketClient;
    private SocketServer socketServer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SocketUtil.context = MainActivity.this;
        // 初始化控件
        initView();
        // 注冊廣播接收器
        register();
        socketServer = new SocketServer();
        socketClient = new SocketClient();
    }
    private void initView() {
        text_file_size = findViewById(R.id.text_file_size);
        button_send = findViewById(R.id.button_send);
        button_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Integer size = Integer.parseInt(text_file_size.getText().toString());
                socketClient.sendFile(size);
            }
        });
        text_info = findViewById(R.id.text_info);
        text_info.setMovementMethod(new ScrollingMovementMethod());
    }
    private void register() {
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String info = intent.getStringExtra("info");
                text_info.append(info + "\n");
            }
        };
        IntentFilter filter = new IntentFilter("main.info");
        registerReceiver(broadcastReceiver, filter);
    }
}

我們將需要重復用到的一些代碼都放到工具類中

public class SocketUtil {
    public static Context context;
    // 一次最多傳輸多少字節
    public static int MAX_CHUNK = 100;
    public static void sendInfo(String info) {
        Intent intent = new Intent("main.info");
        intent.putExtra("info", info);
        context.sendBroadcast(intent);
    }
    // 讀取二進制信息
    public static byte[] readBytes(InputStream inputStream, String log) {
        byte[] len = new byte[3];
        byte[] allbytes = new byte[10000];
        int idx = 0;
        try {
            inputStream.read(len);
            // 然后再根據讀取的長度信息讀取二進制流
            // 只要不是最后一個二進制流就繼續讀取
            while (SocketUtil.parseLen(len) != 0) {
                byte[] temp = new byte[SocketUtil.parseLen(len)];
                inputStream.read(temp);
                idx = SocketUtil.appendBytes(allbytes, temp, idx);
                String info = "[" + log + "]接收一個數據包,大小" + SocketUtil.parseLen(len) + "B";
                SocketUtil.sendInfo(info);
                inputStream.read(len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SocketUtil.getNewArr(allbytes, idx);
    }
    // 將int轉成String
    public static String intToStr(int len) {
        StringBuffer sb = new StringBuffer();
        if(len < 100) {
            sb.append("0");
        }
        else if (len < 10) {
            sb.append("00");
        }
        sb.append(Integer.toString(len));
        return sb.toString();
    }
    public static int parseLen(byte[] len) {
        return Integer.parseInt(new String(len, 0, len.length));
    }
    public static int appendBytes(byte[] arr1, byte[] arr2, int st) {
        for(int i=st; i<arr2.length; i++) {
            arr1[i] = arr2[i-st];
        }
        return arr2.length+st;
    }
    public static byte[] getNewArr(byte[] arr, int idx) {
        byte[] newarr = new byte[idx];
        for(int i=0; i<idx; i++) {
            newarr[i] = arr[i];
        }
        return newarr;
    }
}

最后是定義我們的客戶端和服務端

public class SocketClient {
    private final String HOST = "localhost";
    private final int PORT = 50055;
    private Socket socket = null;
    private OutputStream outputStream = null;
    private InputStream inputStream = null;
    public SocketClient() {
        conn();
        while(socket == null) {}
        SocketUtil.sendInfo("服務端連接成功...");
        try {
            outputStream = socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 連接服務端
    private void conn() {
        new Thread(()->{
            try {
                socket = new Socket(HOST, PORT);
                inputStream = socket.getInputStream();
                while(true) {
                    // 接收服務端消息0
                    byte[] type = new byte[1];
                    inputStream.read(type);
                    if (new String(type, 0, 1).equals("1")) {
                        byte[] infobytes = SocketUtil.readBytes(inputStream, "客戶端");
                        String info = "[客戶端]接收消息:" + new String(infobytes, 0, infobytes.length);
                        SocketUtil.sendInfo(info);
                        SocketUtil.sendInfo("====================================");
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
    // 發送文件
    public void sendFile(int size) {
        new Thread(()->{
            try {
                // 表示發送文件
                outputStream.write("2".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            for(int i=0; i<size/SocketUtil.MAX_CHUNK+1; i++) {
                StringBuffer sb = new StringBuffer();
                if (i!=size / SocketUtil.MAX_CHUNK) {
                    for (int j = 0; j < SocketUtil.MAX_CHUNK; j++) {
                        sb.append('a');
                    }
                }
                else if(i==size/SocketUtil.MAX_CHUNK && size%SocketUtil.MAX_CHUNK==0) {
                    break;
                }
                else {
                    for (int j = 0; j < size % SocketUtil.MAX_CHUNK; j++) {
                        sb.append('a');
                    }
                }
                try {
                    SocketUtil.sendInfo("[客戶端]發送一個數據包,大小" + sb.toString().getBytes().length + "B");
                    // 發送chunk的長度
                    outputStream.write(SocketUtil.intToStr(sb.toString().getBytes().length).getBytes());
                    // 發送chunk塊
                    outputStream.write(sb.toString().getBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 最后發送000表示結束
            try {
                outputStream.write("000".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
public class SocketServer {
    private final int PORT = 50055;
    private ServerSocket serverSocket = null;
    public SocketServer() {
        // 啟動服務端監聽
        start();
        while(serverSocket == null) {}
        SocketUtil.sendInfo("服務端啟動...");
    }
    // 啟動服務端監聽程序
    private void start() {
        new Thread(()->{
            try {
                serverSocket = new ServerSocket(PORT);
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();
                while(true) {
                    byte[] type = new byte[1];
                    inputStream.read(type);
                    String typeinfo = new String(type, 0, 1);
                    if(typeinfo.equals("2")) {
                        byte[] file = SocketUtil.readBytes(inputStream, "服務端");
                        String filetxt = new String(file, 0, file.length);
                        String info = "[服務端]接收完文件,大小" + file.length + "B" + "\n";
                        info = info + "[服務端]具體內容如下:" + "\n" + filetxt;
                        SocketUtil.sendInfo(info);
                        // 給客戶端發送一個響應信息表示接收成功
                        String typetxt = "1";
                        outputStream.write(typetxt.getBytes());
                        String successinfo = "文件接收成功";
                        String lentxt = SocketUtil.intToStr(successinfo.getBytes().length);
                        outputStream.write(lentxt.getBytes());
                        outputStream.write(successinfo.getBytes());
                        outputStream.write("000".getBytes());
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

上述代碼中,服務端只負責接收二進制流,客戶端只負責發送二進流,并且服務端在接收完二進制流數據后,會給服務端返回一個表示接收成功的文字信息。

Android怎么使用socket進行二進制流數據傳輸

到此,相信大家對“Android怎么使用socket進行二進制流數據傳輸”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

哈尔滨市| 东城区| 佛教| 礼泉县| 荔波县| 吉隆县| 昭通市| 资兴市| 桦甸市| 石景山区| 洛南县| 扶风县| 临桂县| 辽宁省| 赫章县| 醴陵市| 泰来县| 陆川县| 大余县| 宜君县| 盐池县| 睢宁县| 新兴县| 遂昌县| 凤凰县| 陆良县| 贺州市| 民县| 堆龙德庆县| 阜平县| 鹰潭市| 阳泉市| 多伦县| 朝阳区| 江川县| 南靖县| 阿拉善盟| 花莲市| 东明县| 资讯| 辉县市|