【问题标题】:Telnet late server replyTelnet 延迟服务器回复
【发布时间】:2014-04-09 22:53:42
【问题描述】:

我在 telnet 通信方面遇到了非常奇怪的问题。当我向服务器发送消息时,服务器将在下一条消息后每次回复。服务器回复如下所示:

// 错误的 IP 发送器地址消息

如果我发送“第一条消息”,服务器将不会回复。在我发送“第二条消息”后,服务器将回复第一条消息。每次来自服务器的回复都会延迟一条消息。 我的通信如下所示:

如果我使用 Google Play 商店中的 Telnet 应用程序,它可以完美运行,通信如下所示:

 C: first message
 S: [// bad IP transmitters adress message 'first message']
 C: second message
 S: [// bad IP transmitters adress message 'second message']
 C: third message
 S: [// bad IP transmitters adress message 'third message']

有什么办法可以解决吗?非常感谢!

代码:

TCP类

public class TCPclass {

private boolean mRun = false;
String messageFromServer;
private OnMessageReceived mMessageListener = null;
PrintWriter out;
BufferedReader in;

public TCPclass(OnMessageReceived listener) {
    mMessageListener = listener;
}

public void stopClient() {
    mRun = false;
}

public void sendMessage(String message) {
    if (out != null && !out.checkError()) {
        message = message + '\r' + '\n';
        out.print(message);
        out.flush();
        Log.i("Terminal", "Message sent.");
    }
}

public void start(String hostname, int port) {
    mRun = true;
    try {
        InetAddress serverAddr = InetAddress.getByName(hostname);

        Socket socket = new Socket(serverAddr, port);

        try {

            out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(socket.getOutputStream())), true);

            // receive the message which the server sends back
            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));

            while (mRun) {
              do
              {

               String messageFromServer = in.readLine();


                if (messageFromServer != null && mMessageListener != null) {
                    mMessageListener.messageReceived(messageFromServer); //append message to Text View
                }
                messageFromServer = null;


             } while (in.ready());
        }

        } catch (Exception e) {
            Log.e("Terminal", "S: Error ", e);
        } finally {
            socket.close();
        }

    } catch (Exception e) {
        Log.e("Terminal", "Establish connection error " + hostname + " "
                + port);
    }
}

public interface OnMessageReceived {
    public void messageReceived(String message);
}
}

MainActivity 类:

public class MainActivity extends Activity {

private TCPclass mTcpClass;
public String hostname = "127.0.0.1";
public int port = 7011;
TextView serverMessage;
private connectTask mTask;

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

    final EditText IPaddress = (EditText) findViewById(R.id.eAddress);
    final EditText ePort = (EditText) findViewById(R.id.ePort);
    final EditText eMessage = (EditText) findViewById(R.id.eMessage);
    serverMessage = (TextView) findViewById(R.id.tOutput);

    Button okButton = (Button) findViewById(R.id.bOK); //Connect button
    okButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) { // connect
            // TODO Auto-generated method stub
            hostname = IPaddress.getText().toString(); 
            String strPort = ePort.getText().toString(); 

            try {
                port = Integer.parseInt(strPort); 

            } catch (NumberFormatException e) {
                Log.e(strPort, "Error port");
            }
            mTask = new connectTask();
            mTask.execute("");
        }
    });

    Button sendButton = (Button) findViewById(R.id.bSend);
    sendButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            String message = eMessage.getText().toString();
            serverMessage.append("C: " + message + "\n");
            Log.i("Terminal", "Sending message " + message);
            if (mTcpClass != null) {
                mTcpClass.sendMessage(message);
            }
            eMessage.setText("");
        }
    });
}

public class connectTask extends AsyncTask<String, String, TCPclass> {
    @Override
    protected TCPclass doInBackground(String... message) {
        Log.i("Terminal", "doInBackground.");

        mTcpClass = new TCPclass(new TCPclass.OnMessageReceived() {
            @Override
            // here the messageReceived method is implemented
            public void messageReceived(String message) {
                // this method calls the onProgressUpdate
                publishProgress(message);
            }
        });
        mTcpClass.start(hostname, port);
        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        serverMessage.append("S: " + Arrays.toString(values) + "\n");
    }
}

【问题讨论】:

  • 您没有显示任何接收代码,我猜想缓冲在那里。
  • 我将代码添加到我的问题中。请看一下。谢谢。
  • 您为什么要使用来自您的previous question 的这个名誉扫地的sendPacket() 代码?它没有达到作者声称的效果。
  • 好的,我添加了完整的代码。 @EJP我在那里添加了'\ r',现在它正在工作,每次延迟一条消息时服务器都会回复。在我问上一个问题之前,服务器根本没有响应。
  • @我不是在谈论 \r,,尽管根据 RFC 肯定应该是 \r\n,除非您已经在 Telnet 中协商了二进制模式。我说的是通过sendMessage()sendPacket() 方法一次发送一个字符并像作者一样假装TCP 不会再次重新合并它们的愚蠢技术。 sendMessage() 应该只附加\r\n 并直接调用print()flush()

标签: java networking telnet


【解决方案1】:

在我看来,服务器可能在您没有考虑到的地方发送了一个空白或额外的行。我是世界上最后一个也是最不喜欢打电话给available()ready() 的人,但也许就是这样:

do
{
    String response = in.readLine();
    // ...
} while (in.ready());

... 至少出于调试目的,直到您准确地弄清楚对您发送的每一行的响应是什么。请注意,在这里使用while 循环肯定是不正确的。

【讨论】:

  • 还是一样的效果,看起来没有更多的空白或多余的行。我从 Wireshark 捕获了服务器消息,它看起来像这样:clip2net.com/s/6XO82z 在数据中只有 12345 和 0d = (CR) 的消息错误 ip
  • 奇怪的是响应以 \r (0xd) 而不是 \r\n 结尾。您可以将当前代码编辑到您的问题中吗?
  • 我上传了。希望我正确使用了您的调试代码。
  • 看起来没问题,虽然如果 readLine() 返回 null 您应该关闭连接并退出读取循环。你能用'\r'试试吗?
  • 顺便说一句。如果我在代码服务器中删除 flush() 将延迟回复 2 条消息。也许这个事实也会有所帮助
猜你喜欢
  • 2017-04-13
  • 2018-05-19
  • 2019-10-09
  • 1970-01-01
  • 2021-04-29
  • 2017-10-07
  • 1970-01-01
  • 2011-09-26
  • 2018-03-17
相关资源
最近更新 更多