TCP en Java (Android Genérico)

Servidor TCP, creando una interfaz de hilo

 

public class TCPServer implements Runnable {
    private static final String TAG = "TCPServer";

    private String chaSet = "UTF-8";

    private int port;
    private boolean isListen = true;
    public TCPServer(int port) {
        this.port = port;
    }

    @Override
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            Log.d(TAG, "run:等待客户端连接... ");
            //serverSocket.setSoTimeout(2000);
            if (isListen) {
                Socket socket = serverSocket.accept();
                Log.d(TAG, "run: 客户端已连接");
                if (socket != null) {
                    accept(socket);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void accept(Socket socket) {
        InputStream is;
        OutputStream os;
        try {
            is = socket.getInputStream();
            os = socket.getOutputStream();
            int len;
            byte[] bytes = new byte[1024 * 4];

            while (!socket.isClosed() && !socket.isInputShutdown()) {
                while ((len = is.read(bytes)) != -1) {
                    Log.d(TAG, "accept: len: " + len);
                    byte[] content = new byte[bytes.length];
                    System.arraycopy(bytes, 0, content, 0, bytes.length);

                    String res = new String(content, chaSet);
                    String trim = res.trim(); //打印的时候去掉多余部分

                    if (onReceiveListener != null) {
                        onReceiveListener.receive(trim);
                    }
                }
            }

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


   //创建回调  用于在主线程中监听收消息事件

    private onReceiveListener onReceiveListener;

    public interface onReceiveListener {
        void receive(String bytes);
    }

    public void setOnReceiveListener(onReceiveListener onReceiveListener) {
        this.onReceiveListener = onReceiveListener;
    }


}

Cree un hilo en el hilo principal y llame al oyente de devolución de llamada de la interfaz:

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);
        TCPServer tcpServer=new TCPServer(9899);
        new Thread(tcpServer).start();
        tcpServer.setOnReceiveListener(new TCPServer.onReceiveListener() {
            @Override
            public void receive(String bytes) {
                Log.d(TAG, "receive: bytes: "+bytes);
            }
        });
    }
}

Luego use el asistente de depuración de red para enviar un mensaje al servidor:

Por último, recuerda solicitar la solicitud de red:

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

Nuevo requisito: definir la estructura de datos requerida para aceptar datos.

De acuerdo con el análisis de longitud de la estructura de datos definida, los bytes recibidos se procesan de la siguiente manera:

        int postX = 0;
        int postY = 0;
        int size = 0;
        int reserveOne = 0;
        int reserveTwo = 0;
        String reserve = "";
        int color = 0;
        long pngLen = 0L;

       postX = getInt(bytes, 0, 4);
       postY = getInt(bytes, 4, 4);
       size = getInt(bytes, 8, 4);
       reserveOne = getInt(bytes, 12, 4);
       reserveTwo = getInt(bytes, 16, 4);
       reserve = getString(bytes, 20, 56);
       color = getInt(bytes, 76, 4);
       pngLen = getInt(bytes, 80, 4);
       if (onReceiveListener != null) {
           onReceiveListener.receive(postX, postY, size, reserveOne, reserveTwo, reserve, color, pngLen);
                  


 //byte转int
    public int getInt(byte[] srcBytes, int srcPos, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(srcBytes, srcPos, bytes, 0, length);
        int anInt = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
        return anInt;
    }


    //byte转String
    public String getString(byte[] srcBytes, int srcPos, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(srcBytes, srcPos, bytes, 0, length);
        String str = "解析错误";
        try {
            str = new String(bytes, 0, length, chaSet);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str.trim();
    }


  

ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt()La función del método es convertir la matriz de bytes dada bytesen un valor entero.

Primero, ByteBuffer.wrap(bytes)se crea un nuevo búfer de bytes y se envuelve alrededor de la matriz de bytes dada bytes. Esto significa que las operaciones posteriores se realizarán en ese búfer.

A continuación, .order(ByteOrder.LITTLE_ENDIAN)establezca el orden de bytes del búfer de bytes en Little Endian. El orden de los bytes determina cómo se almacenan en la memoria los tipos de datos de varios bytes.Little endian significa que los bytes de orden bajo se almacenan en direcciones bajas en la memoria, y los bytes de orden alto se almacenan en direcciones altas en la memoria.

Finalmente, .getInt()se leen cuatro bytes del búfer de bytes y se interpretan como un valor entero. La posición actual del búfer de bytes se desplazará cuatro bytes para la siguiente operación de lectura.

¿Qué es Big Endian Little Endian? Preguntado sobre chatGPT

Big Endian y Little Endian son órdenes de dos bytes que se utilizan para describir cómo se almacenan los datos de varios bytes en la memoria.

En las computadoras, los tipos de datos de varios bytes (como números enteros, números de coma flotante) generalmente constan de varios bytes. Estos bytes se almacenan en la memoria en un orden determinado. Big-endian y little-endian especifican cómo se organizan estos bytes en la memoria.

  • Big Endian: En Big Endian, el byte más significativo (Byte más significativo, MSB) se almacena en la dirección de memoria más baja y el byte menos significativo (Byte menos significativo, LSB) se almacena en el lugar de dirección de memoria más alto. Similar al hábito de escritura de los números, el byte de orden superior viene primero y sigue el byte de orden inferior.

  • Little Endian: en Little Endian, el byte menos significativo (LSB) se almacena en la dirección de memoria más baja y el byte más significativo (MSB) se almacena en la dirección de memoria más alta. Al contrario de big-endian, el byte de orden inferior viene primero y sigue el byte de orden superior.

Aquí hay un ejemplo para ilustrar la diferencia entre big endian y little endian:

Suponiendo un valor entero de cuatro bytes 0x12345678(en representación hexadecimal), se almacena en la memoria de la siguiente manera:

  • Big endian: dirección alta -> baja

    高地址 12 | 34 | 56 | 78 低地址

  • Little endian: dirección bit bajo -> bit alto

    低地址 78 | 56 | 34 | 12 高地址

Tenga en cuenta que big-endian y little-endian difieren solo en el almacenamiento de tipos de datos multibyte. Para los tipos de datos de un solo byte (como los caracteres), el endianness no tiene efecto porque solo tienen un byte. La elección del orden de los bytes tiene significados importantes en diferentes arquitecturas y protocolos de comunicación, especialmente en la comunicación multiplataforma o de red, es crucial manejar correctamente el orden de los bytes.

Supongo que te gusta

Origin blog.csdn.net/m0_56366502/article/details/130643622
Recomendado
Clasificación