我正在开发一种设备,通过传感器测量某些读数。该设备由一个Android应用程序操作。我需要从TCP层获取读数。以下是发送TCP数据的代码:
TcpClient.java
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与设备通信时,无法识别数据包之间的边界。在这种情况下,如果数据包不按顺序或任何数据包丢失,则可以使用“头部开始”来识别新的数据包。 因此,数据包中的前两个字节表示数据包的开头。
头部开始:两个字节的字段,表示每个数据包的开始。0x55AA是用作头部开始的2字节数字。
协议版本:1字节字段,用于指定正在使用的协议版本。在有效载荷中指定的版本将决定有效载荷结构。在任何给定时刻,设备将支持单个协议版本。目前的协议版本为“1”。
DSN:序列号是1字节字段,可唯一标识数据包。请求方必须在请求有效载荷中填写此字段;响应方必须在响应有效载荷中填写相同的唯一标识符。
请求ID:一个字节的字段,指定命令ID。根据命令ID进行有效载荷的解析。在请求有效载荷的情况下,此字段将为非零值,在响应中将为零。
有效载荷长度:两个字节的字段,指定有效载荷的长度(以字节为单位)。它指定了跟随有效载荷长度字段的字节数。在有效载荷长度、头部长度和CRC中不包括。目前,网关设备支持的最大有效载荷长度为512(字节)。 CRC:1字节字段,将通过对所有字节进行异或并添加0的异或计数来计算。
它正在工作。但是根据文档,我必须使用二进制通信协议发送数据包。包括头部开始、有效载荷数据等。如何在数据包结构中发送这些参数?如何创建数据包?
任何帮助都将不胜感激。
DataInputStream
和DataOutputStream
。我会使用一个长度为7的字节数组来存储“Header Start”到“Payload Length”。然后再使用另一个最大长度为2^15的字节数组来存储“Payload Data”和“CRC”。然后将这两个数组连接成一个大小为7 + 2^15的字节数组,并使用DataOutputStream#write(byte[] array, int offset, int length)
写入该数组,其中offset
将为0,length
将为7 + 2^15。但是,这是一种非常低级的方法。 - Jonny Henly