0

我必须在我的应用程序中实现聊天。使用套接字连接到服务器。我应该注册到该服务器,服务器会通过回复来确认这一点。

我已经在一个方法中实现了这一点,我使用 BufferedWriter 发送命令,然后开始从输入流中读取,直到它告诉我没有更多数据。

我正确阅读了服务器回复。但是,我从未从第二次调用中获得负值in.read,因此我的方法在 while 循环中保持阻塞(在我进行该调用的条件语句中)。

这应该如何使用套接字来完成?我通常用文件或其他输入流来做这件事,没有问题。

如果我应该只读取我应该读取的字节,这是否意味着我必须:

  • 提前知道服务器响应的长度?
  • 或者让服务器发送一个代码来通知它已经完成发送响应?

目前我正在做以下事情:

private String sendSocketRequest(String request, boolean skipResponse) throws ChatException {
    if (!isConnected()) openConnection();

    try {
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
                                     socket.getOutputStream()), 2048);
        out.append(request);
        out.flush();
        out = null;
    } catch (IOException e) {
        LogHelper.error("Unable to send socket request: " + request, e);
        throw new ChatException("Unable to send socket request: " + request, e);
    }

    try {
        BufferedReader in = new BufferedReader(new InputStreamReader(
                                     socket.getInputStream()), 2048);
        StringBuffer response = new StringBuffer();
        char[] buffer = new char[2048];
        int charsRead = -1;

// >>>>>>>> This is where it gets blocked <<<<<<<<<

        while ((charsRead = in.read(buffer)) >= 0) {
            if (charsRead > 0) response.append(new String(buffer, 0, charsRead));
        }
        return response.toString();
    } catch (IOException e) {
        LogHelper.error("Unable to read socket response: " + request, e);
        throw new ChatException("Unable to read socket response: " + request, e);
    }
}

使用以下方法连接到服务器:

public synchronized void openConnection() throws ChatException {
    try {
        socket = new Socket(Constants.API_CHAT_SERVER_ADDRESS, Constants.API_CHAT_SERVER_PORT);
        socket.setKeepAlive(true);

        LogHelper.debug("CHAT      >> Connected to the chat server: " + Constants.API_CHAT_SERVER_ADDRESS);
    } catch (UnknownHostException e) {
        LogHelper.error("Unable to open chat connection", e);
        throw new ChatException("Unable to open chat connection", e);
    } catch (IOException e) {
        LogHelper.error("Unable to open chat connection", e);
        throw new ChatException("Unable to open chat connection", e);
    }
}
4

2 回答 2

1

通过基于套接字的连接发送/接收的数据量取决于协议,TCP/IP 堆栈不知道,但只有应用层知道。

使用的协议是开发人员依赖的...... ;-) 所以来回答你的问题:

如果我应该只读取我应该读取的字节,这是否意味着我必须:

  • 提前知道服务器响应的长度?

是的,这是一种可能性。

  • 或者让服务器发送一个代码来通知它已经完成发送响应?

也可以,因为这是另一种可能性。常见的标记是\n\r\n。/字符也可能有意义NUL'\0'

第三种选择是在每个数据块前面加上一个常数字节数来描述即将到来的字节数。

于 2012-11-19T18:09:58.687 回答
1

而不是处理字节,也许它更简单地处理临时类的实例,例如 - 例如 - 一个Message类:

服务器:

// Streams
protected ObjectInputStream fromBuffer = null;
protected ObjectOutputStream toBuffer = null;

// Listening for a new connection
ServerSocket serverConn = new ServerSocket(TCP_PORT);
socket = serverConn.accept();
toBuffer = new ObjectOutputStream(socket.getOutputStream());
fromBuffer = new ObjectInputStream(socket.getInputStream());

// Receiving a new Message object
Message data = (Message)fromBuffer.readObject();

然后客户端通过简单的方式发送消息:

// Sending a message
Message data = new Message("Hello");
toBuffer.writeObject(data);

只要消息的成员实现Serializable接口,消息就可以根据需要变得复杂。

于 2012-11-19T18:44:17.900 回答