Java中的TCP (Android通用)

TCP服务端,创建了一个线程的接口

 

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;
    }


}

在主线程中创建线程,调用接口回调监听:

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);
            }
        });
    }
}

然后用网络调试助手给服务端发消息:

最后记得申请网络请求:

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

新增需求:定义所需要的数据结构接受数据。

根据定义好的数据结构的长度解析,接受到的bytes然后进行如下处理:

        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() 方法的作用是将给定的字节数组 bytes 转换为一个整数值。

首先,ByteBuffer.wrap(bytes) 创建了一个新的字节缓冲区,并将其包装在给定的字节数组 bytes 上。这意味着后续的操作将在该缓冲区上进行。

接下来,.order(ByteOrder.LITTLE_ENDIAN) 设置字节缓冲区的字节顺序为小端序(Little Endian)。字节顺序决定了多字节数据类型在内存中的存储方式,小端序表示低位字节存储在内存的低地址处,高位字节存储在内存的高地址处。

最后,.getInt() 从字节缓冲区中读取四个字节,并将其解释为一个整数值。字节缓冲区的当前位置将被移动四个字节的长度,以便下一次读取操作。

大端小端是什么?询问了chatGPT

大端(Big Endian)和小端(Little Endian)是用于描述多字节数据在内存中的存储方式的两种字节序(byte order)。

在计算机中,多字节数据类型(例如整数、浮点数)通常由多个字节组成。这些字节按照一定的顺序在内存中存储。大端序和小端序指定了这些字节在内存中的排列方式。

  • 大端序(Big Endian):在大端序中,最高有效字节(Most Significant Byte,MSB)存储在最低的内存地址处,最低有效字节(Least Significant Byte,LSB)存储在最高的内存地址处。类似于数字书写习惯,高位字节在前,低位字节在后。

  • 小端序(Little Endian):在小端序中,最低有效字节(LSB)存储在最低的内存地址处,最高有效字节(MSB)存储在最高的内存地址处。与大端序相反,低位字节在前,高位字节在后。

下面是一个示例,用于说明大端序和小端序的区别:

假设有一个四字节的整数值 0x12345678(十六进制表示),它在内存中的存储如下:

  • 大端序:地址高位->低位

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

  • 小端序:地址低位->高位

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

需要注意的是,大端序和小端序仅在多字节数据类型的存储方面有所区别。对于单字节的数据类型(如字符),字节序没有影响,因为它们只有一个字节。字节序的选择在不同的体系结构和通信协议中具有重要的意义,特别是在跨平台或网络通信时,正确处理字节序是至关重要的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值