这几天做一个项目,Socket服务端是C++写的,这几天用了好多办法,平常用的那些socket发送数据的方法都行不通
C++服务端是用结构体写的,但是我看了Java是没有结构体的,我看了java是没有结构体的,这怎么弄,我不懂C++的
我先服务端定义发一下
// 用户登录相关协议
struct
{
char UserName[12];
char Password[18];
char PhoneNum[12];
}ReqUserLog;
struct
{
int UserID;
int ErrCode;
}ReqUserLogResult;
android 客户端该怎样写socket和接收呢?
我叫人C++服务端的人写了一个java例子给我,他发了一个方法给我,但是我看到这个方法还是不知道怎么用
private byte[] buildNetSendData(HashMap<Integer, Long> sendData, String vin) {
ByteBuffer bytesBuf = ByteBuffer.allocate(sendData.size() * 12 + 18);
Iterator iter = sendData.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Integer, Long> entry = (Map.Entry<Integer, Long>) iter
.next();
bytesBuf.putInt(entry.getKey());
bytesBuf.putLong(entry.getValue());
}
byte[] data = new byte[sendData.size() * 12];
System.arraycopy(bytesBuf.array(), 0, data, 0, data.length);
bytesBuf.clear();
byte[] data_en = new byte[data.length];
int n = data.length / 12;
String v_s = vin.substring(vin.length() - 12, vin.length());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(v_s);
}
String v_pwd = sb.toString();
byte[] v_pwdbytes = v_pwd.getBytes();
if (data.length == v_pwdbytes.length) {
for (int i = 0; i < data.length; i++) {
data_en[i] = (byte) (data[i] ^ v_pwdbytes[i]);
}
}
bytesBuf.put(vin.getBytes());
bytesBuf.put((byte) 0x01);
bytesBuf.put(data_en);
bytesBuf.flip();
return bytesBuf.array();
}
请各位知道的帮忙一下,这个socket该怎么写,最好有个发送和接收的例子
非常感谢
这是文档协议
协议ID |
类型 |
长度 |
备注 |
ID = 0d22000 |
int |
1 |
用户登录信息指令 |
UserName |
Char |
12 |
用户名 |
Password |
Char |
18 |
密码 |
PhoneNum |
Char |
12 |
登录的手机号码 |
|
|||
协议ID |
类型 |
长度 |
备注 |
ID = 0d22001 |
int |
1 |
保存用户注册信息返回结果 |
UserID |
Int |
1 |
用户ID(获取用户信息时用此ID做参数) |
ErrCode |
Int |
1 |
0:成功 -1:用户名不存在 -2:密码错误 |
我这样写着,调不通,那个大神看看,我哪里写错了
我这样写,为什么还是不行
定义一个类
package com.homemonitor.model.struct;
public class Login_Info{
public static int length = 33;
private byte[] buf = new byte[1 + 12 + 18 + 12];
public int cmdId = 0;
public String userName = "";
public String password = "";
public String phoneNum = "";
/* 构造并转换 */
public Login_Info(int cmdId, String userName, String password, String phoneNum) {
this.cmdId = cmdId;
this.userName = userName;
this.password = password;
this.phoneNum = phoneNum;
byte[] temp = toLH(cmdId);
System.arraycopy(temp, 0, buf, 20, temp.length);
temp = userName.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);
temp = password.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);
temp = phoneNum.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);
}
private static String toStr(byte[] valArr, int startpoint, int maxLen) {
int index = 0;
while (index + startpoint < valArr.length && index < maxLen) {
if (valArr[index + startpoint] == 0) {
break;
}
index++;
}
byte[] temp = new byte[index];
System.arraycopy(valArr, startpoint, temp, 0, index);
return new String(temp);
}
public static String get_login_info(byte[] bArr) {
int id = 0;
int userId = 0;
int errCode = 0;
byte[] temp = new byte[3];
id = vtolh(bArr);
System.arraycopy(bArr, 1, temp, 0, 1);
userId = vtolh(temp);
System.arraycopy(bArr, 2, temp, 0, 3);
errCode = vtolh(temp);
return "id=" + id + ",userId=" + userId + "," + "errCode=" + errCode;
}
protected static byte[] toLH(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将低字节在前转为int,高字节在后的byte数组
*/
protected static int vtolh(byte[] bArr) {
int n = 0;
for(int i=0;i<bArr.length&&i<4;i++){
int left = i*8;
n+= (bArr[i] << left);
}
return n;
}
/* 返回要发送的数组 */
public byte[] getBuf() {
return buf;
}
}
调用
try {
InetSocketAddress = new InetSocketAddress("120.25.246.140", 5000);
Socket socket_client = new Socket();
socket_client.connect(addr);
if (client_socket == null)
return;
int available = 0;
Login_Info sendmsg = new Login_Info(22000, "hello", "123456", "18088881111");
byte[] receive = new byte[3];
int available = 0;
Login_Info sendmsg = new Login_Info(cmd, userName, password, phoneNum);
try {
if ((available = socket.getInputStream().available()) >= 0)
{
socket.getInputStream().read(new byte[available]);
socket.getInputStream().skip(available);
}
socket.getOutputStream().write(sendmsg.getBuf());
socket.getOutputStream().flush();
socket.getInputStream().read(receive);
String result = Login_Info.get_login_info(receive);
}
catch (IOException e) {
e.printStackTrace();
}
}
catch (Exception ex) {
System.out.println("ex===" + ex.getMessage());
}
...这个东西关结构体什么事儿?
通讯传输的都是二进制数据,这么怎么编码的,那边怎么解码不就可以了...
我按照你最后给的文档协议来回答:
ByteBuffer bytesBuf = ByteBuffer.allocate(sizeof(int) + 12 + 18 + 12);
bytesBuf.PutInt(0x0d22000); // 用户登录信息指令,没考虑网络字节序和主机字节序的问题,你需要同他们确定。
bytesBuf.("User".getBytes()); // 用户名,假设为 unicode 双字节编码,同时 "User" 长度小于 12 字节。
bytesBuf.("Pwd".getBytes()); // 密码,假设为 unicode 双字节编码,同时 "Pwd" 长度小于 18 字节。
bytesBuf.("Phone".getBytes()); // 手机号,假设为 unicode 双字节编码,同时 "Phone" 长度小于 12 字节。
Socket.Send(bytesBuf.Array()); // 发送登录数据包
PS: 我不知道这个协议是否描述完整,一般来说需要对数据作封包设计,也就是上面的数据只是包体,包体前一般有 4 个字节来表示包体的长度。
我这样写,为什么还是不行
定义一个类
package com.homemonitor.model.struct;
public class Login_Info{
public static int length = 33;
private byte[] buf = new byte[1 + 12 + 18 + 12];
public int cmdId = 0;
public String userName = "";
public String password = "";
public String phoneNum = "";
/* 构造并转换 */
public Login_Info(int cmdId, String userName, String password, String phoneNum) {
this.cmdId = cmdId;
this.userName = userName;
this.password = password;
this.phoneNum = phoneNum;
byte[] temp = toLH(cmdId);
System.arraycopy(temp, 0, buf, 20, temp.length);
temp = userName.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);
temp = password.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);
temp = phoneNum.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);
}
private static String toStr(byte[] valArr, int startpoint, int maxLen) {
int index = 0;
while (index + startpoint < valArr.length && index < maxLen) {
if (valArr[index + startpoint] == 0) {
break;
}
index++;
}
byte[] temp = new byte[index];
System.arraycopy(valArr, startpoint, temp, 0, index);
return new String(temp);
}
public static String get_login_info(byte[] bArr) {
int id = 0;
int userId = 0;
int errCode = 0;
byte[] temp = new byte[3];
id = vtolh(bArr);
System.arraycopy(bArr, 1, temp, 0, 1);
userId = vtolh(temp);
System.arraycopy(bArr, 2, temp, 0, 3);
errCode = vtolh(temp);
return "id=" + id + ",userId=" + userId + "," + "errCode=" + errCode;
}
protected static byte[] toLH(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将低字节在前转为int,高字节在后的byte数组
*/
protected static int vtolh(byte[] bArr) {
int n = 0;
for(int i=0;i<bArr.length&&i<4;i++){
int left = i*8;
n+= (bArr[i] << left);
}
return n;
}
/* 返回要发送的数组 */
public byte[] getBuf() {
return buf;
}
}
调用
try {
InetSocketAddress = new InetSocketAddress("120.25.246.140", 5000);
Socket socket_client = new Socket();
socket_client.connect(addr);
if (client_socket == null)
return;
int available = 0;
Login_Info sendmsg = new Login_Info(22000, "hello", "123456", "18088881111");
byte[] receive = new byte[3];
int available = 0;
Login_Info sendmsg = new Login_Info(cmd, userName, password, phoneNum);
try {
if ((available = socket.getInputStream().available()) >= 0)
{
socket.getInputStream().read(new byte[available]);
socket.getInputStream().skip(available);
}
socket.getOutputStream().write(sendmsg.getBuf());
socket.getOutputStream().flush();
socket.getInputStream().read(receive);
String result = Login_Info.get_login_info(receive);
}
catch (IOException e) {
e.printStackTrace();
}
}
catch (Exception ex) {
System.out.println("ex===" + ex.getMessage());
}
1楼已经说得很明白了。再告诉你一个好用的框架 protobuf
自己解决了