简体   繁体   English

如何从插座读取JSON数据而不是一行?

[英]How to read JSON data instead of a line from socket?

My application connects to a sensor over WiFi direct. 我的应用程序通过WiFi直接连接到传感器。 Then it connects to a socket and is supposed to read data. 然后,它连接到套接字,并应该读取数据。 The data is JSON and looks like {"d":{temp_mC";33416,"humidity_ppm"...more data....}}. The sensor sends data every 2 minutes. Before I only have been able to read lines that are sent by a server but since the sensor does not send lines I need to redo my TCPClient class. I think that I could implement this code. 数据是JSON,看起来像{“ d”:{temp_mC“; 33416,” humidity_ppm“ ... more data ....}}。传感器每2分钟发送一次数据。在我只能读取行之前由服务器发送,但是由于传感器不发送线,我需要重做TCPClient类,我认为我可以实现此代码。

ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = socket.getInputStream().read(buffer)) != -1) {
result.write(buffer, 0, length);
}
// StandardCharsets.UTF_8.name() > JDK 7
return result.toString("UTF-8");

To get the JSON data into a string, then I would have to parse it but that is for later. 要将JSON数据转换为字符串,则必须对其进行解析,但这将在以后提供。

My old code looks like this, does anyone have an idea how I could remake my old code to implement above method or a similar method so I can read the JSON data and turn it into a string so I can parse it later? 我的旧代码看起来像这样,是否有人知道如何重新制作旧代码以实现上述方法或类似方法,以便我可以读取JSON数据并将其转换为字符串,以便以后进行解析?

TcpClient 的TcpClient

public class TcpClient {

....

/**
 * 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
 */

/**
 * Close the connection and release the members
 */
public void stopClient() {

    mRun = false;

    mMessageListener = null;
    mBufferIn = 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 {


            //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);
}

}

My AsyncClass in other activity 我在其他活动中的AsyncClass

  public class ConnectTask extends AsyncTask<String, String, TcpClient> {

    @Override
    protected TcpClient doInBackground(String... message) {

        //we create a TCPClient object
        mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
            @Override
            //here the messageReceived method is implemented
            public void messageReceived(String message) {
                //this method calls the onProgressUpdate
                publishProgress(message);
            }
        });
        mTcpClient.run();

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        CO2 = values[0];
        //response received from server
        Log.d("CO2", values[0]);
        //process server response here....

    }

}

The proper way to deal with such case is to send the entire data at once. 处理这种情况的正确方法是立即发送全部数据。

This is possible by first sending the data size and then the data content like this: 首先发送数据大小,然后发送数据内容,如下所示:

outputStream.writeInt(message.length); 
outputStream.write(message);

and when reading the message, parse the length and then read the entire message like this: 在阅读消息时,解析长度,然后像这样读取整个消息:

int len = socketDataInputStream.readInt();                    
byte[] message = new byte[len];
socketDataInputStream.readFully(message, 0, message.length);

Hope this helps, goodluck. 希望这有帮助,祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM