Custom Android Socket communication module (1): socket related knowledge

I made a Socket encapsulation module for Android and device communication before, which is used for data exchange with the device, which greatly solves the complexity and confusion of the old code and provides scalability. Next, I will slowly introduce the various parts of this communication module in several blogs, and realize the desired design into specific functions step by step!

The following briefly introduces the use of Socket.

Document preparation

The socket code in Java is under the java.net package, you can look it up under the Android official document, but it is in English:

developer.android.google.cn/reference/k…

developer.android.google.cn/reference/k…

Client usage

Here is a brief introduction to the usage of the Socket client, followed by encapsulation. After all, the connection to the device depends on the client.

Simple usage
public void onClick(View view){<!-- -->
        new Thread(){<!-- -->
            @Override
            public void run() {<!-- -->
                super. run();
                try {<!-- -->
                    //1. Create and listen to the specified server address and the port number that the specified server listens to
                    Socket socket = new Socket("111.111.11.11", 12306);//111.111.11.11 is the IP address of my machine, and the port number is 12306.
                    //2. Get the output stream of the client's socket object and send it to the server data
                    OutputStream os = socket. getOutputStream();
                    //write the data to be sent to the server
                    os.write(et.getText().toString().getBytes());
                    os. flush();
                    socket. shutdownOutput();
                    //Get the input stream of the socket, where the data returned by the server is stored
                    InputStream is = socket. getInputStream();
                    // Parse the data returned by the server
                    InputStreamReader reader = new InputStreamReader(is);
                    BufferedReader bufReader = new BufferedReader(reader);
                    String s = null;
                    final StringBuffer sb = new StringBuffer();
                    while((s = bufReader. readLine()) != null){<!-- -->
                        sb.append(s);
                    }
                    runOnUiThread(new Runnable() {<!-- -->
                        @Override
                        public void run() {<!-- -->
                            tv.setText(sb.toString());
                        }
                    });
                    //3. Close the IO resources (note: in actual development, it needs to be placed in finally)
                    bufReader. close();
                    reader. close();
                    is. close();
                    os. close();
                    socket. close();
                } catch (UnknownHostException e) {<!-- -->
                    e.printStackTrace();
                } catch (IOException e) {<!-- -->
                    e.printStackTrace();
                }
            }
        }.start();

    }
Simple packaging

After learning the simple usage of Socket, let’s encapsulate it into Service. The following is a simplified code, only talking about Socket connection and receiving, and other things will be slowly explained in the follow-up content:

public class ConnectService extends Service {<!-- -->

    /** Socket related, IP and port number **/
    private String ip = "192.168.1.110";
    private int port = 2050;
    private int wait = 5000;
    
    private Socket mSocket;
    private Thread rxThread;

    //initialize the connection
    public void setUpConnection() throws IOException {<!-- -->

        //Close the existing socket
        stopExistSocket();

        //Create a new socket
        createSocket();

        //Start the receiving thread
        startRxThread();
    }

    private void stopExistSocket() throws IOException {<!-- -->

        if (mSocket != null) {<!-- -->
            try {<!-- -->
                mSocket. close();
                mSocket = null;
            } catch (IOException e) {<!-- -->
                e.printStackTrace();
                throw e;
            }
        }
    }

    private void createSocket() throws IOException {<!-- -->

        SocketAddress sa = new InetSocketAddress(ip, port);
        mSocket = new Socket();
        try{<!-- -->
            //Set information and timeout
            mSocket. connect(sa, wait);
            boolean isConnect = mSocket. isConnected();
            mSocket.setKeepAlive(isConnect);
        } catch(IOException e) {<!-- -->
            mSocket = null;
            throw e;
        }
    }

    private void startRxThread() {<!-- -->

        if (rxThread == null || !rxThread.isAlive()) {<!-- -->
            rxThread = initReceiveThread();
            rxThread. start();
        }
    }
    
    //accept thread
    private Thread initReceiveThread() {<!-- -->

        return new Thread(new Runnable() {<!-- -->
            @SuppressWarnings("ResultOfMethodCallIgnored")
            @Override
            public void run() {<!-- -->
                try {<!-- -->
                    InputStream is;
                    while (mSocket != null) {<!-- -->
                        is = mSocket. getInputStream();

                        byte[] ackbuf = new byte[4]; //message number
                        int ackrs = is.read(ackbuf, 0, 4);
                        if (ackrs < 0) {<!-- -->
                            Thread. sleep(1000);
                            continue;
                        }

                        //TODO process data by itself
                        ...
                    }
                }catch(IOException e) {<!-- -->
                    e.printStackTrace();
                } catch(Exception e) {<!-- -->
                    e.printStackTrace();
                }
            }
        });
    }
}
Tell me briefly

In fact, there are only three steps here. It is very simple to close the existing socket, create a new socket, and start the receiving thread. If there is any defect, it is that the stream is not closed properly. I will change it when I have time!

Server code

The Socket server is not used to connect with the device, so I will write a simple example here! A simulated server is encapsulated, which can be understood at a glance:

public class SimulateUtil {<!-- -->
    
public static class SocketServer extends Thread {<!-- -->
        private Socket remotePeer;
        private SocketServer(Socket remotePeer) {<!-- -->
            this.remotePeer = remotePeer;
        }
        public void run() {<!-- -->
            try {<!-- -->
                InputStream is = null;
                while(remotePeer!= null) {<!-- -->
                    isHxz = remotePeer. getInputStream();
                    //It is very large and can be written as a constant
                    byte[] ackbuf = new byte[2560];
                    int len = is.read(ackbuf, 0, 2560);
                    if (len <= 0) {<!-- -->
                        Thread. sleep(1000);
                        continue;
                    }

                    // Pretend to return data after a while
                    Thread. sleep(1000L + ((int) (Math. random() * 10)) * 100L);
                    remotePeer.getOutputStream().write("hey boy!".getBytes());
                }
            } catch(IOException e) {<!-- -->
                e.printStackTrace();
            } catch(Exception e) {<!-- -->
                e.printStackTrace();
            }
        }
    }

/**
     * Start the simulation process
     */
    public static void startSimulate() {<!-- -->
        new Thread(() -> {<!-- -->
            try {<!-- -->
                ServerSocket serverSocket = new ServerSocket(54321);
                while (true) {<!-- -->
                    Socket remotePeer = serverSocket. accept();
                    new SocketServer(remotePeer).start();
                }
            } catch (IOException e) {<!-- -->
                e.printStackTrace();
            }
        }).start();
    }
}

The following is how to use it, just start it in the application:

SimulateUtil.startSimulate();

be careful:

  • Here the IP is the local address (127.0.0.1)

  • The port number we set is 54321

  • To close the stream or something, you can refer to the following code:

     @Override
        public void run() {<!-- -->
    InputStreamReader reader = null;
            BufferedReader bufReader = null;
            OutputStream os = null;
            try {<!-- -->
                reader = new InputStreamReader(socket. getInputStream());
                bufReader = new BufferedReader(reader);
                String s = null;
                StringBuffer sb = new StringBuffer();
                while((s = bufReader. readLine()) != null){<!-- -->
                    sb.append(s);
                }
                System.out.println("Server:" + sb.toString());
                // close the input stream
                socket. shutdownInput();
                
                //return data to client
                os = socket. getOutputStream();
                os.write(("I am the server, the data sent to me by the client is:" + sb.toString()).getBytes());
                os. flush();
                socket. shutdownOutput();
            } catch (IOException e2) {<!-- -->
                e2.printStackTrace();
            } finally{<!-- -->//Close IO resources
                if(reader != null){<!-- -->
                    try {<!-- -->
                        reader. close();
                    } catch (IOException e) {<!-- -->
                        e.printStackTrace();
                    }
                }
                
                if(bufReader != null){<!-- -->
                    try {<!-- -->
                        bufReader. close();
                    } catch (IOException e) {<!-- -->
                        e.printStackTrace();
                    }
                }
                if(os != null){<!-- -->
                    try {<!-- -->
                        os. close();
                    } catch (IOException e) {<!-- -->
                        e.printStackTrace();
                    }
                }
            }
        }
    

Conclusion

Well, here is a brief talk about the use of sockets, all of which are TCP connections, because this is part of the “Custom Android Socket Communication Module Series” written by me, so it is more biased towards specific uses, if readers want To learn more about the use of socket, you can refer to the following article, which I think is very well written:

www.jianshu.com/p/fb4dfab4e…

In addition, if readers want to continue to understand my “Custom Android Socket Communication Module Series” article, you can click on the link to jump to view it!

end