android自定义url协议,Android使用自定义TCP协议访问网络(以二进制流的方式)

该博客介绍了一种自定义TCP协议的实现,包括协议头(包含魔数和长度字段)和JSON格式的协议内容。通过Java的Socket进行网络通信,实现了向服务器发送数据并接收响应的功能。主要涉及字节操作、网络IO和接口回调的设计。
部署运行你感兴趣的模型镜像

由于服务器是自己搭建,直接使用TCP的Socket进行访问,并且传输的是自定义格式数据帧,只提供主机地址和端口号,并没有请求的url,所以请求服务器不能使用现在的OKHttp等访问网络的框架。

协议规范

协议头+协议内容

协议头

MAGIC+LENGHT

MAGIC:魔数, 固定为”0x8EEEEEEE”(自定义的十六进制), unsigned int型, 4个字节

LENGTH:协议内容的长度, unsigned int型, 4字节

协议内容

格式为json字符串

需要注意大小端的区别

java.nio.ByteOrder.LITTLE_ENDIAN:将低序字节存储在起始地址(低位编址)

java.nio.ByteOrder.BIG_ENDIAN:将高序字节存储在起始地址(高位编址)

x86系列CPU都是little-endian的字节序。

简单的封装代码如下

/**

* Created by lexwu on 2017/1/23.

* Socket访问网络封装

*/

public class HttpUtil {

private static final String HOST = "10.100.0.100";//主机地址

private static final int PORT = 9000;//端口号

//TCP向服务端发送数据

public static void requestServer(String json, CallListener callListener) {

byte[] bytes1 = hexStringToByteArray("8EEEEEEE");//将自定义的16进制魔数转变为二进制的流

byte[] bytes2 = intToBytes(json.length(), ByteOrder.BIG_ENDIAN);//将协议头的LENGHT转变为二进制的byte,第二个参数是大端

byte[] byte3 = json.getBytes(); //将json数据转换为二进制的流

byte[] bys = addBytes(bytes1, bytes2);//合并byte数组

final byte[] bytes = addBytes(bys, byte3);//将3个byte数组合并为一个

Socket socket = null;

OutputStream output = null;

InputStream input = null;

StringBuffer sb = null;

try {

socket = new Socket(HOST, PORT);

//--------向服务端的写入信息-------------

output = socket.getOutputStream();

output.write(bytes);// 把msg信息写入输出流中

//--------接收服务端的返回信息-------------

socket.shutdownOutput(); // 一定要加上这句,否则收不到来自服务器端的消息返回 ,意思就是结束msg信息的写入

input = socket.getInputStream();

byte[] b = new byte[1024];

int len = -1;

sb = new StringBuffer();

while ((len = input.read(b)) != -1) {

sb.append(new String(b, 0, len, Charset.forName("UTF-8")));// 得到返回信息

}

} catch (Exception e) {

callListener.onError();//请求失败的回调

e.printStackTrace();

} finally {

try {

if (socket != null) {

output.flush();

String jsonResult = sb.substring(8);//截取服务器返回的数据

callListener.onResult(jsonResult);//请求成功的回调

socket.close();// 释放资源,关闭这个Socket

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

所用到的工具类

/**

* Created by lexwu on 2017/1/23.

* HttpUtil所用到的工具类

*/

public class ByteUtil {

/**

* 将2个byte数组进行拼接

*/

public static byte[] addBytes(byte[] data1, byte[] data2) {

byte[] data3 = new byte[data1.length + data2.length];

System.arraycopy(data1, 0, data3, 0, data1.length);

System.arraycopy(data2, 0, data3, data1.length, data2.length);

return data3;

}

/**

* int转byte{}

*/

public static byte[] intToBytes(int value, ByteOrder mode) {

byte[] src = new byte[4];

if (mode == ByteOrder.LITTLE_ENDIAN) {

src[3] = (byte) ((value >> 24) & 0xFF);

src[2] = (byte) ((value >> 16) & 0xFF);

src[1] = (byte) ((value >> 8) & 0xFF);

src[0] = (byte) (value & 0xFF);

} else {

src[0] = (byte) ((value >> 24) & 0xFF);

src[1] = (byte) ((value >> 16) & 0xFF);

src[2] = (byte) ((value >> 8) & 0xFF);

src[3] = (byte) (value & 0xFF);

}

return src;

}

/**

* 16进制表示的字符串转换为字节数组

*

* @param s 16进制表示的字符串

* @return byte[] 字节数组

*/

public static byte[] hexStringToByteArray(String s) {

int len = s.length();

byte[] b = new byte[len / 2];

for (int i = 0; i < len; i += 2) {

// 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节

b[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character

.digit(s.charAt(i + 1), 16));

}

return b;

}

}

网络请求接口

/**

* Created by lexwu on 2017/1/23.

* 网络请求接口回调

*/

public interface CallListener {

void onResult(String jsonresult);

void onError();

}

您可能感兴趣的与本文相关的镜像

Facefusion

Facefusion

AI应用

FaceFusion是全新一代AI换脸工具,无需安装,一键运行,可以完成去遮挡,高清化,卡通脸一键替换,并且Nvidia/AMD等显卡全平台支持

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值