套接字客户端:没有得到DataInputStream.readUTF()的完整响应

时间:2016-05-31 16:18:25

标签: java sockets client

我想编写一个套接字客户端来向服务器发送请求并获得响应。它有效,但不对。 这是我的代码:

public String send(final String data) {
        Socket client = null;
        String response = null;

        try {
            client = new Socket(this.host, this.port);

            final OutputStream outToServer = client.getOutputStream();
            final DataOutputStream out = new DataOutputStream(outToServer);
            out.writeUTF(data);

            final InputStream inFromServer = client.getInputStream();
            final DataInputStream in = new DataInputStream(inFromServer);
            response = in.readUTF();
        } catch (final IOException e) {
            this.log.error(e);
            this.log.error("Sending message to server " + this.host + ":" + this.port + " fail", e);
        } finally {
            if (client != null) {
                try {
                    client.close();
                } catch (final IOException e) {
                    this.log.error("Can't close socket connection to " + this.host + ":" + this.port, e);
                }
            }
        }
        if (StringUtils.isBlank(response)) return null;
        return response;
    }

问题是:我没有得到in.readUTF()的完整回复。我总是得到一个响应,其长度与发送数据的长度(变量data)相同。我已经使用其他GUI客户端进行了测试并得到了完整的响应。所以这不是服务器的问题。 有人知道吗,我做错了什么?

更新

感谢EJP和Andrey Lebedenko。我认为,我的问题是函数writeUTFreadUTF。所以我在try块中编辑了我的代码,所以:

        Charset charset = Charset.forName("ISO-8859-1");
        final OutputStream outToServer = client.getOutputStream();
        final DataOutputStream out = new DataOutputStream(outToServer);
        out.write(data.getBytes(charset));

        final InputStream inFromServer = client.getInputStream();
        final BufferedReader in = new BufferedReader(new InputStreamReader(inFromServer, charset));
        response = in.readLine();

它现在有效。

2 个答案:

答案 0 :(得分:1)

如果它适用于Telnet,根据您的评论,服务器未使用readUTF(),因此您的writeUTF()已经错误,因此服务器不太可能使用{{1}或者,这也会使你的writeUTF()错误。您不能任意使用这些方法:它们只能在它们之间交换数据。

我敢打赌你工作的GUI客户端也不会使用它们。

答案 1 :(得分:0)

在不知道服务器部分做什么的情况下,追踪根本原因是很困难的(如果可能的话)。所以最诚实的希望是,我会分享这段代码,我已经对上面的片段进行了测试。

package tcpsendreceive;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SendReceive {
    private static final Logger log = Logger.getLogger(SendReceive.class.toString());

    private final String host;
    private final int port;

    private Server server;

    class Server extends Thread
    {
        private final ServerSocket serverSocket;
        public Server(ServerSocket s)
        {
            serverSocket = s;
        }

        @Override
        public void run()
        {
            Socket connection;
            SendReceive.this.log.log(Level.INFO, "Server: DoubleEcho Server running on "+this.serverSocket.getLocalPort());
            try{
                do {
                    connection = this.serverSocket.accept();
                    SendReceive.this.log.log(Level.INFO, "Server: new connection from "+connection.getRemoteSocketAddress());
                    int b;
                    do {
                        DataInputStream in = new DataInputStream(connection.getInputStream());
                        String s = in.readUTF();

                        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                        out.writeUTF(s+","+s); // echo it back TWICE

                        out.flush();
                        connection.shutdownOutput();
                        connection.close();
                    } while(!connection.isClosed());
                }
                while(true);
            }
            catch(IOException ioe)
            {
                SendReceive.this.log.log(Level.SEVERE, "IOException in server! - STOP", ioe);
            }
            finally {
                try{
                    this.serverSocket.close();
                } catch (Exception e) {
                    SendReceive.this.log.log(Level.SEVERE, "IOException closing server! - FATAL", e);
                }
                try{
                    if(!connection.isClosed())
                      connection.close();
                } catch (Exception e) {
                    SendReceive.this.log.log(Level.SEVERE, "IOException closing server! - FATAL", e);
                }
            }
        }
    }

    public SendReceive(String host, int port)
    {
        this.host = host;
        this.port = port;
        try{
            this.server = new Server(new ServerSocket(this.port));
            this.server.start();
        }
        catch(IOException ioe)
        {
            this.log.log(Level.SEVERE, "IOException while creating server! - STOP", ioe);
        }
    }

    public String send(final String data) {
        Socket client = null;
        String response = null;

        try {
            client = new Socket(this.host, this.port);

            final OutputStream outToServer = client.getOutputStream();
            final DataOutputStream out = new DataOutputStream(outToServer);
            out.writeUTF(data);

            final InputStream inFromServer = client.getInputStream();
            final DataInputStream in = new DataInputStream(inFromServer);
            response = in.readUTF();
        } catch (final IOException e) {
            this.log.log(Level.SEVERE, "Sending message to server " + this.host + ":" + this.port + " fail", e);
        } finally {
            if (client != null) {
                try {
                    client.close();
                } catch (final IOException e) {
                    this.log.log(Level.SEVERE, "Can't close socket connection to " + this.host + ":" + this.port, e);
                }
            }
        }
        if(response == null || response.isEmpty()) 
            return null;

        return response;
    }    
}

试验演示

package tcpsendreceive;

public class Main {
    public static void main(String[]  args)
    {    
        String data = "AAABBB";
        SendReceive sr = new SendReceive("localhost", 5000);
        String res = sr.send(data);
        System.out.println("Sent: "+data);
        System.out.println("Received: "+res);
    }
}

结果(关键部分):

Sent: AAABBB
Received: AAABBB,AAABBB

希望它有所帮助。

修改的 1.更正了包装器刷新而不是套接字流刷新。仍然认为在关闭套接字之前冲洗流包装是一种好习惯。

  1. 客户端套接字在IOException块中关闭(因为它们在ServerSocket关闭时不会自动关闭)。谢谢@EJP
  2. P.S。我应该承认,我对这种简陋的测试服务器代码的关注感到有些惊讶,特别是与我们在SO上看到的其他脏测试相比。受宠若惊。 :)