Java Telnet延迟服务器回复

Java Telnet延迟服务器回复,java,networking,telnet,Java,Networking,Telnet,我在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: [// ba

我在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']
//IP地址信息错误

如果我发送“第一条消息”,服务器将不会回复。在我发送“第二条消息”后,服务器将回复第一条消息。每次服务器的回复都会延迟一条消息。 我的沟通是这样的:

 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']

如果我使用Google Play Store的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);
}
}
主要活动类别:

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");
    }
}
公共类MainActivity扩展活动{
私有TCPclass mTcpClass;
公共字符串hostname=“127.0.0.1”;
公共int端口=7011;
TextView服务器消息;
私有连接任务mTask;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
最终EditText IPaddress=(EditText)findViewById(R.id.eadAddress);
最终EditText ePort=(EditText)findViewById(R.id.ePort);
最终EditText eMessage=(EditText)findViewById(R.id.eMessage);
serverMessage=(TextView)findViewById(R.id.tOutput);
按钮OK按钮=(按钮)findViewById(R.id.bOK);//连接按钮
setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图arg0){//connect
//TODO自动生成的方法存根
hostname=IPaddress.getText().toString();
字符串strPort=ePort.getText().toString();
试一试{
端口=整数.parseInt(strPort);
}捕获(数字格式){
Log.e(strPort,“错误端口”);
}
mTask=新连接任务();
mTask.execute(“”);
}
});
按钮sendButton=(按钮)findViewById(R.id.bSend);
setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图v){
String message=eMessage.getText().toString();
serverMessage.append(“C:+message+”\n”);
Log.i(“终端”、“发送消息”+消息);
如果(mTcpClass!=null){
mTcpClass.sendMessage(消息);
}
e消息。setText(“”);
}
});
}
公共类connectTask扩展了AsyncTask{
@凌驾
受保护的TCPclass doInBackground(字符串…消息){
Log.i(“终端”、“后台”);
mTcpClass=新的TCPclass(新的TCPclass.OnMessageReceived(){
@凌驾
//这里实现了messageReceived方法
已接收公共无效消息(字符串消息){
//此方法调用onProgressUpdate
出版进度(信息);
}
});
mTcpClass.start(主机名、端口);
返回null;
}
@凌驾
受保护的void onProgressUpdate(字符串…值){
super.onProgressUpdate(值);
serverMessage.append(“S:+Arrays.toString(values)+“\n”);
}
}

在我看来,服务器可能在某个地方发送了一个空白行或额外的行,而您还没有解释。我是世界上最后一个也是最不喜欢调用
available()
ready()
的人,但可能就是这样:

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

…至少出于调试的目的,直到您对发送的每一行的响应进行准确排序。请注意,在此处使用
while
循环肯定是不正确的。

您没有显示任何接收代码,我猜是在那里缓冲。我将代码添加到我的问题中。请看一看。谢谢。您为什么要使用正在删除此不可信的
sendPacket()
来自您的代码?它不符合作者的要求。好吧,我添加了完整的代码。@EJP我在那里添加了“\r”,现在它只在服务器回复每一条延迟的消息时工作。在我问之前,服务器根本没有响应。@我不是在谈论
\r,
,尽管这当然应该是
\r\n
r RFC,除非您在Telnet中协商过二进制模式。我指的是一种愚蠢的技术,即通过
sendMessage()
sendpackage()
方法一次发送一个字符,并假装TCP不会再次合并它们。
sendMessage()
应该只追加
\r\n
并直接调用
print()
flush()
。仍然是一样的效果,看起来没有多余的空白行。我从wireshark捕获了服务器消息,它看起来是这样的:在数据中,只有12345和0d=(CR)的错误ip消息奇怪的是,响应以\r(0xd)not \r\n结尾。您能将当前代码编辑到您的问题中吗?我已上载。希望我正确使用了调试代码。它看起来不错,但如果readLine()返回null,您应该关闭连接并退出读取循环。您能用“\r”尝试吗?顺便说一句,如果我删除flush()在代码中,服务器将延迟回复2条消息。也许这一事实也会有所帮助