我必须在我的应用程序中实现聊天。使用套接字连接到服务器。我应该注册到该服务器,服务器将通过回复知道。
我已经在一个方法中使用BufferedWriter发送命令,然后从输入流开始读取,直到它告诉我没有更多数据。
我正确阅读了服务器回复。但是,我从来没有从第二个in.read
调用中获得负值,因此我的方法在while循环中保持阻塞(在我进行该调用的conditionnal语句中)。
如何使用套接字完成此操作?我通常使用文件或其他输入流来做到这一点。
如果我只读取我应该阅读的字节,那是否意味着我要么:
目前我正在做以下事情:
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);
}
}
答案 0 :(得分:1)
通过基于套接字的连接发送/接收的数据量是协议依赖的,并且TCP / IP堆栈不知道,但仅限于应用层。
使用的协议是开发人员依赖... ;-)所以提出你的问题:
如果我只读取我应该阅读的字节,那是否意味着我要么:
- 事先知道服务器响应的长度吗?
是的,这是一种可能性。
- 或让服务器发送代码通知它已完成发送响应?
同样是的,因为这是另一种可能性。常见标记为\n
或\r\n
。 NUL
/ '\0'
字符也可能有意义。
第三个选项是为每个数据块添加一个常量字节数,用于描述要传输的字节数。
答案 1 :(得分:1)
而不是处理字节,也许它更简单地处理ad-hoc类的实例,例如 - 消息类:
服务器:
// 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 接口。