来自套接字的Java读取消息未发送完整消息

时间:2014-02-10 16:52:12

标签: java sockets

你好我正在使用这种方法来阅读一条消息:

public String readMessage() {
    int read = -1;
    byte[] buffer = new byte[5*1024];
    byte[] redData;
    try {
        while ((read = this.session.getInputStream().read(buffer)) > -1) {
            redData = new byte[read];
            System.arraycopy(buffer, 0, redData, 0, read);
            return new String(redData,"UTF-8");

        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

当我写下“你好,今天你好吗?”时,

回复(确切格式,包括这些新行):

[/127.0.0.1:54930]:     
[/127.0.0.1:54930]: are

[/127.0.0.1:54930]: you

[/127.0.0.1:54930]: today?

这是我如何阅读聊天消息,首先我检查请求了哪个数据包,如果数据包类型为0,那么我获得了packethandler的实例,并将客户端对象传递给Chat处理数据包,这将在此处读取消息,如这样:

public void startClientService() throws IOException {
    while(true) {
        int packetType = this.in.read();
        packets.getPacket(packetType);
    }
}
public void getPacket(int packetType) {
    switch (packetType) {
    case 0:
        chat.processPacket(this.client);
        break;
    }
}

和聊天包:

@Override
public void processPacket(Session c) {
    String clientMessage = c.readMessage();
    System.out.println("[" + c.getStream().getRemoteSocketAddress() + "]: " + clientMessage.toString());
}

然后就会出现打印消息。

为什么要用新行打印部分消息?甚至没有完整的信息。

这是我的客户:

public static void main(String[] args) throws UnknownHostException, IOException {
    Socket socket = new Socket("127.0.0.1", 43594);
    Scanner r = new Scanner(System.in);
    PrintWriter out = new PrintWriter(socket.getOutputStream());
    String input;
    while(true) {
        input = r.next();
        if (input != null) {
            sendMessage(input, out);
        }
    }

}

public static void sendMessage(String message, PrintWriter out) {
    out.write(0);
    out.flush();
    out.write(message + "\n");
    out.flush();
}

感谢。

会话:

public class Session extends Thread implements Runnable {

    private Socket session;
    private Client client;
    private PrintWriter out;
    private BufferedReader in;  
    private PacketHandler packets;

    public Session(Socket session) {
        this.session = session;
        this.client = new Client(this);
        try {
            this.setStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.packets = new PacketHandler(this);
        System.out.println("[New session created]: " + session.getRemoteSocketAddress());
    }   

    public void run() {
        try {
            this.startClientService();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Socket getStream() {
        return this.session;
    }

    public void setStream() throws IOException {
        this.out = new PrintWriter(this.session.getOutputStream());
        this.in = new BufferedReader(new InputStreamReader(this.session.getInputStream()));
    }

    public Client getClient() {
        return this.client;
    }

    public String readMessage() {
        int read = -1;
        byte[] buffer = new byte[5*1024];
        byte[] redData;
        try {
            while ((read = this.session.getInputStream().read(buffer)) > -1) {
                redData = new byte[read];
                System.arraycopy(buffer, 0, redData, 0, read);
                return new String(redData,"UTF-8");

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void startClientService() throws IOException {
        while(true) {
            int packetType = this.in.read();
            packets.getPacket(packetType);
        }
    }

    public void destruct() throws IOException {
        this.session.close();
        System.out.println("Session killed");
    }

}

2 个答案:

答案 0 :(得分:1)

一旦你从流中获得一些数据,

就好像你正在返回。

  while ((read = this.session.getInputStream().read(buffer)) > -1) {
            redData = new byte[read];
            System.arraycopy(buffer, 0, redData, 0, read);
            return new String(redData,"UTF-8");

        }

完全读取数据并从中生成一个字符串对象并将其返回

    BufferedReader br = new BufferedReader(new InputStreamReader(this.session.getInputStream()));
String msg = br.readLine();
br.close();
    return msg;

试试这种方式。这将为缓冲区提供整个数据,并可以作为字符串返回。不需要循环

答案 1 :(得分:0)

从一次调用返回到read的数据量与如何调用无关 数据在发送时被分割。一次发送可以导致任意数量的读取和多次发送 可以合并为一个阅读。