2016-10-06 36 views
0

我需要使用來自我的android應用程序的套接字將數據包發送到服務器。我只知道一個包的佈局:android java socket寫入和接收byte []數據

Packet ID 4 bytes | Packet length 4 bytes(minus len + ID) | payload (protobuf message) 

關於TLSv1.2連接和自簽名證書的整個工作很好。例如,我需要發送認證數據包 - 如果數據包發送成功,LoginRequest和服務器將響應LoginResponse。我正在嘗試做的是連接到AsyncTask類中的服務器,寫入數據並接收響應,但顯然我做錯了,因爲我沒有迴應。對於寫作和閱讀信息的代碼:

LoginRequest protobuf的消息:

Protos.LoginRequest loginRequest = Protos.LoginRequest.newBuilder() 
        .setUsername(mailAddress) 
        .setPassword(pass).build(); 

和代碼(內部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(); 

正如我說我沒有迴應,有時在閱讀郵件時我也會遇到SSLException:

javax.net.ssl.SSLException: Read error: ssl=0xb3a28580: I/O error during system call, Connection timed out 

有沒有人有ide一個如何解決這個問題?

//修訂 我想通了,字節順序需要在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); 

但現在我得到OOM異常:

Failed to allocate a 184549388 byte allocation with 16777216 free bytes and 155MB until OOM 

詳細信息關於此問題: 寫入DataOutputStream後,我將:

buffer.clear() 
out.flush(); 

//code for reading from InputStream 

而現在,在我的日誌出現此消息幾次: 啓動阻斷GC的Alloc

,比拋出OOM異常。

回答

0

您正在編寫數據包類型,長度和有效負載,但您只是讀取有效負載。你還假設read()填充緩衝區。

int type = din.readInt(); 
int length = din.readInt(); 
byte[] data = new byte[length]; 
din.readyFully(data); 
+0

感謝您的提示,但仍然不工作,它堅持閱讀。發送數據包可能是問題所在,但我無法弄清楚。 – slena17

+0

如果此代碼卡在讀取中,另一端不發送此協議。 – EJP

0

問題出在LITTLE_ENDIAN和BIG_ENDIAN的順序。服務器將在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); 
} 

謝謝你的提示。