gpt4 book ai didi

Android TCP Socket InputStream 间歇读取或太慢

转载 作者:行者123 更新时间:2023-12-03 11:50:13 26 4
gpt4 key购买 nike

我需要在 IoT 设备(自定义)和 Android 应用程序之间实现 TCP 通信。对于 Wifi 设备,我们有一个Server Socket,而在 Android 中,我有一个 AsyncTask 作为客户端 Socket。设备和智能手机都连接到同一网络。

这是用于初始化/套接字读取和套接字写入的 Android Client Socket 代码:

变量:

static public Socket nsocket; //Network Socket
static public DataInputStream nis; //Network Input Stream
static private OutputStream nos; //Network Output Stream

AsyncTask 方法 doInBackgroud:

@Override
protected Boolean doInBackground(Void... params) { //This runs on a different thread
boolean result = false;

try {
//Init/Create Socket
SocketInit(IP, PORT);

// Socket Manager
SocketUpdate();
} catch (IOException e) {
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: IOException");
clearCmdInStack();
MainActivity.SocketDisconnectAndNetworkTaskRestart();
result = true;
} catch (Exception e) {
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: Exception");
result = true;
} finally {
try {
SocketDisconnect();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.i("AsyncTask", "doInBackground: Finished");
}
return result;
}

套接字初始化:

public void SocketInit(String ip, int port) throws IOException {
InetAddress addr = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
nsocket = new Socket();
nsocket.setReuseAddress(false);
nsocket.setTcpNoDelay(true);
nsocket.setKeepAlive(true);
nsocket.setSoTimeout(0);
nsocket.connect(sockaddr, 0);
StartInputStream();
StartOutputStream();
}

从套接字读取:

private void SocketUpdate() throws IOException, ClassNotFoundException {
int read = 0;
// If connected Start read
if (socketSingleton.isSocketConnected()) {
// Print "Connected!" to UI
setPublishType(Publish.CONNECTED);
publishProgress();

if(mConnectingProgressDialog != null)
mConnectingProgressDialog.dismiss(); //End Connecting Progress Dialog Bar

//Set Communications Up
setCommunicationsUp(true);

Log.i("AsyncTask", "doInBackground: Socket created, streams assigned");
Log.i("AsyncTask", "doInBackground: Waiting for inital data...");
byte[] buffer = new byte[3];

do{
nis.readFully(buffer, 0, 3);
setPublishType(Publish.READ);

publishProgress(buffer);
}while(!isCancelled());
SocketDisconnect();
}
}

流初始化:

public void StartInputStream() throws IOException{
nis = new DataInputStream(nsocket.getInputStream());
}

public void StartOutputStream() throws IOException{
nos = nsocket.getOutputStream();
}

读写方法:

public int Read(byte[] b, int off, int len) throws  IOException{
return nis.read(b, off, len); //This is blocking
}

public void Write(byte b[]) throws IOException {
nos.write(b);
nos.flush();
}

public boolean sendDataToNetwork(final String cmd)
{
if (isSocketConnected())
{
Log.i("AsyncTask", "SendDataToNetwork: Writing message to socket");
new Thread(new Runnable()
{
public void run()
{
try
{
Write(cmd.getBytes());
}
catch (Exception e)
{
e.printStackTrace();
Log.i("AsyncTask", "SendDataToNetwork: Message send failed. Caught an exception");
}
}
}).start();

return true;
}

Log.i("AsyncTask", "SendDataToNetwork: Cannot send message. Socket is closed");
return false;
}

应用程序非常简单,android 应用程序向物联网设备发送命令(通过 sendDataToNetwork 方法),后者发回“ACK”命令字符串。


问题

问题是,虽然 IoT 设备始终接收命令,但智能手机很少收到 ACK。有时我会收到类似“ACKACKACKACK”的信息。通过调试 IoT 设备,我确定它成功发回了 ACK,因此问题出在 InputStream read() 方法中,该方法不会立即检索字符串。

有没有办法立即清空 InputStream 缓冲区,以便我每次发送命令时都能从物联网设备返回一个“ACK”字符串?


更新

我更新了套接字配置,不再有缓冲区限制,并且我用 readFully 替换了 read() 方法。它有了很大的改进,但仍然会犯一些错误。例如,有 2-3 次中有 1 次没有收到 ack,我在下一回合收到 2 次 ack。这可能是 IoT 设备的计算限制吗?还是还有改进方法的余地?

最佳答案

the problem lies in the InputStream read() method which doesn't empty the buffer right away.

我不知道这里的“清空缓冲区”是什么意思,但是 InputStream.read() 被指定为在传输一个字节后立即返回。

Is there a way to empty the InputStream buffer right away, so that i get an "ACK" string back from the IoT device every time i send a command?

实际的问题是您一次可以读取多个 的ACK。还有其他的。

  1. 如果您正试图读取三个字节,您应该使用 DataInputStream.readFully() 和一个包含三个字节的字节数组。
  2. 这也将消除对以下数组副本的需要。
  3. 你不应该弄乱套接字缓冲区大小,除非增加它们。 20 和 700 都是非常小的值,不会是实际使用的值,因为平台可以调整提供的值。你声称这种改进的东西是不可信的。
  4. available() 为零时,您不应该自旋循环。这实际上是在浪费时间。您的评论说您在以下阅读电话中被阻止。你不是,尽管你应该是。你在这里旋转。删除它。

关于Android TCP Socket InputStream 间歇读取或太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42393586/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com