5

我有一个连接到服务器的客户端。服务器和客户端以字符串格式交换数据。问题是,服务器在消息末尾没有使用 '\n' 字符,因此客户端在readLine()方法中被阻止。不幸的是,服务器端无法更改。如何从流中读取末尾没有'\n'的那种消息?

我的客户代码:

public class json 
{

    private static Socket socket;

    public static void main(String args[])
    {

        String sendMessage = "";

        Gson gson = new Gson();
        JSON_package authentication = new JSON_package();
        authentication.setType("Identifying");
        authentication.setSource("exampleClient");

        Package_Parser pp = new Package_Parser();

        sendMessage = gson.toJson(authentication);


        sendMessage = authentication.buildPackage(sendMessage);

        try
        {
            String host = "host_address";
            int port = port_number;
            InetAddress address = InetAddress.getByName(host);

            System.out.println("Connecting.");

            socket = new Socket(address, port);
            System.out.println("Connected.");

            //Send the message to the server
            OutputStream os = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os);
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write(sendMessage);
            bw.flush();
            System.out.println("Message sent to the server : "+sendMessage);

            //Get the return message from the server
            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            String message = br.readLine();

            message = pp.Parser(message);

            System.out.println("Message received from the server : " +message);
        }
        catch (Exception exception) 
        {
            exception.printStackTrace();
        }
        finally
        {
            //Closing the socket
            try
            {
                socket.close();
                System.out.println("Closed.");
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}
4

3 回答 3

5

您可以尝试使用readyread(char c)方法。这是一个例子:

StringBuffer sb = new StringBuffer();
while (br.ready()) {
    char[] c = new char[] { 1024 };
    br.read(c);
    sb.append(c);
}
于 2013-07-17T21:46:54.157 回答
1

最简单的解决方案是按字符读取消息字符,但这里的主要问题是要知道消息何时完成。在面向行的协议中,这很简单,发送的换行符是消息之间的“分隔符”。如果没有,有两种可能的情况可以轻松解决此问题:

情况1:消息末尾总是有一个固定字符,不能出现在消息中

// let's pretend ! is the end of message marker
final char endMarker = '!';

// or of course StringBuffer if you need to be treadsafe
StringBuilder messageBuffer = new StringBuilder();
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
    char c = (char)value;
    // end?  jump out
    if (c == endMarker) {
        break;
    }
    // else, add to buffer
    messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();

情况2:消息有固定长度

// let's pretend message is always 80 long
int messageLength = 80;

StringBuilder messageBuffer = new StringBuilder();
int charactersRead = 0;
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
    char c = (char)value;
    // end?  jump out
    if (++charactersRead >= messageLength) {
        break;
    }
    // else, add to buffer
    messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();

在这两种情况下,您都必须添加一些代码来检查您收到的内容的完整性,您可能在阅读期间收到了 EOF。

如果没有明显的消息分隔符并且消息具有可变长度,那将更加困难。

于 2013-07-17T21:47:02.410 回答
0

的重点readLine()是读取真正保证输入将以换行符结尾的数据。通常,在解析输入时,必须有一些标记- 输入中的某个字符或字符组合,您可以使用它来决定是否

  • 等待更多输入
  • 用你已经得到的信息做一些事情
    • 并且可能决定之后是否返回等待更多输入

如果你不能保证会发送一个换行符,那么readLine()这个工作的工具是错误的。改用类似字符数组读取方法的方法InputStreamReader。您将不得不迭代您读入的字符数组,并确定何时有足够的输入可以使用。您还可以使用一次一个字符的read()方法,InputStreamReader该方法将导致更简单但可能效率较低的代码。

如果您使用 的字符数组版本read(),并且如果您在解析了一些输入后返回收集输入,请不要忘记将剩余的内容放回队列中以进行下一轮处理。

于 2013-07-17T22:09:08.153 回答