我试图想出一个好头衔,但似乎失败了。这是我的问题:
我正在从套接字读取数据。缓冲区中包含的数据是序列化对象。一旦数据被完全读取,我就可以创建一个ObjectInputStream并使用readObject来读入数据。
我的问题是,因为我的socket类正在读取字节...我怎么知道什么时候收到完整的对象?似乎没有对象指示符的结束,并且我已经尝试查找序列化字节码的突破以查看我是否可以找到长度字段,但序列化字节码在我可以找到的任何地方都没有得到很好的解释。< / p>
我收到的对象是哈希映射(java.util.Map),如果这有所不同。
以下是我正在使用的代码的一部分:
long start = System.currentTimeMillis();
long end = start + (getTimeout() * 1000);
m_Ipports.send(dataToSend);
m_Waiting = true;
while (m_Waiting) {
// Data is read in a separate thread, and stored into the byte buffer m_DataIn
if (System.currentTimeMillis() > end) {
//throw new Exception("Timeout waiting for response.");
m_Waiting = false; // hack to get it to work. Times out every time.
}
m_Ipports.doEvents();
}
ByteArrayInputStream bis = new ByteArrayInputStream(m_DataIn.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Object o = ois.readObject();
Map m = (Map)o;
所以,我的问题是,当我正在阅读m_DataIn时,我如何确定我已经到达了对象的末尾?
注意:我无法以任何方式修改我从中接收这些对象的服务器。这不是我的代码。
感谢。
查尔斯。
答案 0 :(得分:3)
发送对象的流需要为您提供它将发送的字节数。当您读取指定的字节数时,您将知道已经读完了该对象。
答案 1 :(得分:2)
为什么要从套接字读取字节?只需将ObjectInputStream直接附加到套接字并读取对象。
答案 2 :(得分:0)
嗯,IPWorks IPPortS(SSL)类对于我所需要的几乎所有其他实例都非常有用。它使SSL通信变得轻而易举......就像4行代码和几个事件处理程序一样。一个问题是从流中读取对象。我没有使用ssl套接字来实现自己的解决方案,而是实现了自己的输入流。希望有一天这对其他人有用。
输入流类:
class NetworkInputStream extends InputStream {
private int m_Offset = 0;
private ByteArrayOutputStream m_Buffer = null;
Ipports m_Ipports = null;
public NetworkInputStream(Ipports ipport) {
m_Ipports = ipport;
m_Buffer = new ByteArrayOutputStream();
try { m_Ipports.receiveStream(m_Buffer); } catch (Exception e) {}
m_Offset = 0;
}
public void waitForData() throws Exception {
if (dataAvailable() == 0) {
m_Buffer.reset();
m_Offset = 0;
}
while (dataAvailable() == 0 && m_Ipports.isConnected()) {
m_Ipports.doEvents();
}
}
private int dataAvailable() {
return m_Buffer.size() - m_Offset;
}
public int read(byte[] buffer, int offset, int length) throws IOException, IndexOutOfBoundsException {
try {
waitForData();
} catch (Exception e) {
throw new IOException(e.getMessage()); }
int bytesRead = -1;
int dataAvailable = dataAvailable();
if (dataAvailable > 0) {
bytesRead = Math.min(dataAvailable, length);
m_Buffer.toByteArray();
System.arraycopy(m_Buffer.toByteArray(), m_Offset, buffer, offset, length);
m_Offset += bytesRead;
}
return bytesRead;
}
@Override
public int read() throws IOException {
byte[] buf = new byte[] { 0x00 };
int rval = read(buf, 0, 1);
if (rval == -1) return rval;
int cast = (int)buf[0] & 0xff;
return cast;
}
}
用法:
m_Ipports.setSSLStartMode(Ipports.sslImplicit);
m_Ipports.setTimeout(60);
m_Ipports.setRemoteHost(host);
m_Ipports.setRemotePort(port);
m_Ipports.setConnected(true);
NetworkInputStream nis = new NetworkInputStream(m_Ipports);
m_Ipports.setAcceptData(true);
m_Ipports.send(dataToSend);
ObjectInputStream ois = new ObjectInputStream(nis);
Object resp = ois.readObject();
m_Ipports.setAcceptData(false);
m_Ipports.setReceiveStream(null);
Map m = (Map)o;
我省略了IPPortS的事件处理程序,唯一真正需要的是:
public void SSLServerAuthentication(IpportsSSLServerAuthenticationEvent e) {
e.accept = true;
}
现在,假设您将获得一个完整的对象以响应请求。这就是我与之交互的服务器的工作方式。
查尔斯。