【问题标题】:Reading Lines Correctly Using Telnet使用 Telnet 正确读取行
【发布时间】:2015-02-27 18:08:05
【问题描述】:

我有一个 Android 应用程序,它应该接收和读取 NMEA 句子

例如$GPGLL,3751.65,S,14507.36,E*77

来自使用 Telnet 协议的远程 TCP 服务器。我正在使用org.apache.commons.net.telnet.TelnetClient 库。

什么有效:

  • 连接到服务器

  • 阅读一些句子没有任何错误

问题: 有一半以上的句子缺失。我想这是一个时间问题,也许这也与每次迭代都会重新启动的连接有关。

这是我的MainActivity.java

package com.example.clienttel;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.commons.net.telnet.TelnetClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Go to ClientThread, where NMEA-sentences will be received
        int i;
        for (i = 0; i < 10000; i++)     // 10000 for testing
            new Thread(new ClientThread()).start();
    }

    class ClientThread implements Runnable {
        //@Override
        public void run() {
            TelnetClient telnet = new TelnetClient();

            // Variables
            String ADDRESS = "194.66.82.11";
            int PORT = 51000;
            String NMEA = null;
            final String TAG = "TestApp";

            // Connect To Server
            try {
                telnet.connect(ADDRESS, PORT);
            } catch (IOException e) {
                e.printStackTrace();
            }

            // Process NMEA-sentences
            InputStream inStream = telnet.getInputStream();
            BufferedReader r = new BufferedReader(new InputStreamReader(inStream));

            try {
                NMEA = r.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            // Ignore "...busy" sentences
            if (NMEA != null) {
                if(!(NMEA.equals("*** Serial port is busy ***"))) {
                    Log.i(TAG, NMEA);
                }
            }

            // Disconnect From Server
            try {
                telnet.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

任何帮助将不胜感激!

编辑:

我的代码现在看起来像这样:

package com.example.clienttel;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;

import org.apache.commons.net.telnet.TelnetClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends ActionBarActivity {
    // Variables
    public String ADDRESS = "194.66.82.11";
    public int PORT = 50100;
    public String NMEA = null;
    public final String TAG = "TestApp";
    public boolean first = true;


    // Handler in mainthread
    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            String dataString = "";
            Bundle bundle = msg.getData();

            Log.d("handleMessage", bundle.toString());
            if (bundle.containsKey("outgoingString")) {
                dataString = bundle.getString("outgoingString");
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ClientThread ct;
        ct = new ClientThread();
        ct.mhandler=handler;

        int i;
        for (i = 0; i < 10000; i++) {     // 10000 for testing
            // Go to ClientThread, where NMEA-sentences will be received
            //new Thread(new ClientThread()).start();
            ct.start();
        }
    }

    class ClientThread implements Runnable {
        public Handler mhandler = null;
        @Override
        public void run() {
            TelnetClient telnet = new TelnetClient();

            if (first) {
                // Connect To Server in 1st Iteration
                try {
                    telnet.connect(ADDRESS, PORT);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                first = false;
            }

            // Process NMEA-sentences
            InputStream inStream = telnet.getInputStream();
            BufferedReader r = new BufferedReader(new InputStreamReader(inStream));

            try {
                NMEA = r.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            // Handler in ClientThread to send back
            Bundle b = new Bundle();

            b.putString("outgoingString", NMEA);

            Message m = mhandler.obtainMessage();
            m.setData(b);
            mhandler.sendMessage(m);
        }
    }
}

但我不确定处理程序的位置

【问题讨论】:

  • 连接,只读一行,断开连接,效率极低。你为什么做这个?您应该保持连接并继续从中读取行,直到流结束,如果发生这种情况,或者直到您的应用程序需要退出。
  • 为什么每行有不同的线程?
  • 使用new Thread(new ClientThread()).start(); 我正在创建线程,对吧?为了多次调用线程,我尝试了ClientThread.start();,但它在IDE中抛出了一个错误

标签: java android telnet


【解决方案1】:

正如@EJP 所说,为每一行打开一个关闭连接将杀死应用程序...

更好的方法是让线程处理通信并等待下一行,将数据作为捆绑消息传递回主线程。

那里有很多例子,但本质上你是在你的主线程中创建一个处理程序:

Handler handler = new Handler()
{
    public void handleMessage(Message msg)
    {

        String dataString = "";

        Bundle bundle = msg.getData();

        Log.d("handleMessage", bundle.toString());
        if (bundle.containsKey("outgoingString"))
        {
            dataString = bundle.getString("outgoingString");

        }

        // you can handle other message types here....
   }

并将它(处理程序)传递给您的 ClientThread(此处为 mhandler),您可以将消息发回:

Bundle b = new Bundle();

b.putString("outgoingString", outgoingText);
Message m = mhandler.obtainMessage();
m.setData(b);
mhandler.sendMessage(m);

【讨论】:

  • 感谢您的回答!我按照你的提议引入了一个新的处理程序;我还调整了与服务器的连接(它只在第一次迭代中连接,然后保持)。我刚刚测试了代码(编辑,上面),但应用程序突然崩溃了......我不确定主线程和客户端线程中的处理程序的放置是否有意义。有什么想法吗?
  • 处理程序需要在 onCreate() 方法之外(实例化很好,但引用应该是 MainActivity 类的一部分)。您还需要将处理程序传递给 ClientThread 实例——例如: ClientThread ct = new ClientThread(); ct.mhandler=处理程序; ct.start(); [相对于开始创建,就像你现在正在做的那样]
  • 处理程序现在位于 onCreate() 方法之外。但是通过将处理程序传递给客户端线程,我仍然有点挣扎(请参阅上面的更新代码);在ct.mhandler=handler; 之后,IDE 建议创建字段“mhandler”,并且在ct.start(); 之后,它建议创建一个新的“start”方法(对不起,这些基本问题,我还是 Java 新手)
  • 你有处理程序 mhandler = null;在 run() 方法中定义。使其成为“公共处理程序 mhandler = null;”在 ClientThread 类的顶层部分,以便可以从实例化器(主线程)以及您的内部类访问它。
  • 处理程序现在似乎没问题,但 IDE 仍然抱怨 ct.start() 的 .start()。我认为 .start() 不能在这里使用,因为ClientThread ct; ct = new ClientThread(); ct.mhandler=handler; 不是真正的线程,而是一个类(它只是命名为“ClientThread”)?
猜你喜欢
  • 2011-10-30
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多