[英]android java socket write and receive byte[] data
I need to sent a packet to a server using socket from my android application. 我需要使用我的android应用程序中的套接字将数据包发送到服务器。 I only know a packet layout:
我只知道数据包的布局:
Packet ID 4 bytes | Packet length 4 bytes(minus len + ID) | payload (protobuf message)
The whole stuff about TLSv1.2 connection and self-signed certificate works well. 有关TLSv1.2连接和自签名证书的所有内容都运作良好。 For example, I need to send authentication packet - LoginRequest and server will response with LoginResponse if the packet was sent successfully.
例如,我需要发送身份验证数据包-如果成功发送了数据包,LoginRequest和服务器将使用LoginResponse进行响应。 What I am trying do to is connect to a server inside AsyncTask class, write data and receive response, but obviously I am doing it wrong because I got no response.
我想做的是连接到AsyncTask类内的服务器,写入数据并接收响应,但是显然我做错了,因为我没有响应。 The code for writing and reading a message:
用于编写和阅读消息的代码:
LoginRequest protobuf message: LoginRequest protobuf消息:
Protos.LoginRequest loginRequest = Protos.LoginRequest.newBuilder()
.setUsername(mailAddress)
.setPassword(pass).build();
And the code(inside doInBackground() method): 和代码(在doInBackground()方法内部):
//TLSSocketFactory is custom SSLSocketFactory class for forcing TLSv1.2 on devices > 16 & < 20
socket = tlsSocketFactory.createSocket("airwave1.exurion.com", 2559);
byte[] payload = loginRequest.toByteArray();
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
InputStream inStream = socket.getInputStream();
out.writeInt(10); //ID of the packet
out.writeInt(payload.length);
out.write(payload);
out.flush();
byte[] data = new byte[100];
int count = inStream.read(data);
out.close();
inStream.close();
socket.close();
As I said I got no response, Sometimes I also get an SSLException while reading the message: 正如我说的那样,我没有回应,有时在阅读消息时也会收到SSLException:
javax.net.ssl.SSLException: Read error: ssl=0xb3a28580: I/O error during system call, Connection timed out
Has anyone an idea how to solve this? 有谁知道如何解决这个问题?
//UPDATED I figured out that the byte order needs to be in LITTLE_ENDIAN, so I tried to use ByteBuffer: // UPDATED我发现字节顺序必须是LITTLE_ENDIAN,所以我尝试使用ByteBuffer:
//based on previous packet layout (4 bytes for ID, 4 bytes for payload length, and payload) - is it ByteBuffer.allocate() fine?
ByteBuffer buffer = ByteBuffer.allocate(8 + payload.length);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(LoginPacketType.LOGIN_REQUEST.getId());
buffer.putInt(payload.length);
buffer.put(payload);
buffer.rewind();
byte[] result = new byte[buffer.capacity()]; // Could also use result = buffer.array();
buffer.get(result);
out.write(result);
But now I am getting OOM exception: 但是现在我收到OOM异常:
Failed to allocate a 184549388 byte allocation with 16777216 free bytes and 155MB until OOM
Details about that: After writing to an DataOutputStream, I make: 有关的详细信息:写入DataOutputStream后,我将执行以下操作:
buffer.clear()
out.flush();
//code for reading from InputStream
And now, in my log appears this message several times: Starting a blocking GC Alloc 现在,我的日志中多次出现此消息: 启动阻塞GC Alloc
and than throws OOM exception. 然后抛出OOM异常。
The problem was with LITTLE_ENDIAN and BIG_ENDIAN order. 问题出在LITTLE_ENDIAN和BIG_ENDIAN订单上。 Servers sends response in LITTLE_ENDIAN order so I rewrite your answer a bit:
服务器以LITTLE_ENDIAN的顺序发送响应,因此我将您的答案做了一些重写:
int type = inStream.readInt();
type = Integer.reverseBytes(type);
int length = inStream.readInt();
length = Integer.reverseBytes(length);
if (length > 0) {
byte[] data = new byte[length];
inStream.readFully(data);
Protos.LoginResponse response = Protos.LoginResponse.parseFrom(data);
}
Thanks for the hint. 感谢您的提示。
You're writing a packet type and length and payload, but you're only reading a payload. 您正在编写一个数据包类型,长度和有效负载,但您只读取了一个有效负载。 You're also assuming that
read()
fills the buffer. 您还假设
read()
填充了缓冲区。
int type = din.readInt();
int length = din.readInt();
byte[] data = new byte[length];
din.readyFully(data);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.