我正在研究一種可以通過傳感器測量一些讀數的設備。設備由Android應用運行。我必須從TCP層讀取數據。這是爲了在發送TCP數據如何在TCP端口上使用二進制通信協議發送數據包
TcpClient.java
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
/**
* Created by shahbaz on 25/4/17.
*/
public class TcpClient {
public static final String SERVER_IP = "192.168.1.76"; //server IP address
public static final int SERVER_PORT = 1800;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* @param message text entered by client
*/
public void sendMessage(String message) {
if (mBufferOut != null && !mBufferOut.checkError()) {
mBufferOut.println(message);
mBufferOut.flush();
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
分組格式包含, 雖然與設備上進行通信的代碼TCP,數據包之間的邊界未被識別,在這種情況下,如果數據包無序或者如果丟失了任何數據包,可以使用「標題開始」標識新的數據包。 因此,數據包中的前2個字節表示數據包的開始。
標題開始:指示每個分組開始的雙字節字段。 0x55AA是一個2字節的數字,用作標題開始。
協議版本:單字節字段,用於指定所用協議的版本。有效負載中指定的版本將決定有效負載結構。在任何時候,設備將支持單協議版本。目前的協議版本是'1'。
DSN:序列號是1字節的字段,它將唯一標識數據包。數據包的請求者將不得不填充請求有效載荷中的該字段;響應者必須在響應有效載荷中填充相同的唯一標識符。
請求ID:單字節字段指定命令ID。有效負載的解析將根據命令ID完成。在請求有效載荷的情況下,該字段將不爲零,並且在響應的情況下將爲零。
有效載荷長度:雙字節字段以字節爲單位指定有效載荷的長度。它指定了緊隨有效載荷長度字段的字節數。在有效載荷長度中,不包括標題長度和CRC。目前,網關設備支持的最大有效載荷長度爲512(字節)。 CRC:1個字節的字段,它將通過對所有字節進行異或並將XOR計數加0. 0
它正在工作。但根據文檔,我必須使用二進制通信協議發送數據包。包括標題開始,有效載荷數據,等等。我怎樣才能發送這些參數在數據包結構?我如何創建數據包?
任何幫助表示讚賞。
廣東話份額文檔。只是想知道如何發送這些參數 –
因爲你正在處理髮送字節,你(可能)會想要使用'DataInputStream'和'DataOutputStream'。我使用一個長度爲'7'的字節數組來通過'Payload Length'來存儲'Header Start'。然後另一個字節數組,最大長度爲((2^15)),以存儲「Payload Data」和「CRC」。然後,我將兩個數組連接成一個大小爲'7 +(2^15)'的字節數組,並使用'DataOutputStream#write(byte [] array,int offset,int length)'寫入該數組,'offset'爲'0','長度'爲'7 +(2^15)'。然而這是一個非常低水平的方法。 –
你可以請用一些代碼發佈答案。那麼有效載荷數據呢?它會是什麼結構 –