我编写了一个可运行的网络类,它可以侦听套接字并解组输入。它还可以使用编组对象写入套接字。出现问题是因为套接字保持打开状态(为了以后允许客户端和主机之间的通信) - 这会导致输入流的解组挂起。我尝试从发送方编写XMLStreamConstants.END_DOCUMENT,但这会导致错误解组而不是挂起。以下是网络类的一些代码:
@Override
public void update(Observable o, Object arg) {
try {
if(!this.updatedByNetwork){
OutputStream os = socket.getOutputStream();
mh.marshal(this.gm.getBoard(), os);
os.flush();
}
}catch (IOException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
if (this.ss != null){
this.socket = this.ss.accept();
this.update(this.gm, null);
}
while (true){
try {
InputStream is = socket.getInputStream();
Board b = mh.unmarshal(is);
this.updatedByNetwork = true;
this.gm.updateBoard(b);
} catch (SocketTimeoutException e){
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
这是我的马歇尔处理程序的代码:
public Board unmarshal(InputStream in) throws JAXBException{
Unmarshaller um = this.jc.createUnmarshaller();
Board b = (Board) um.unmarshal(in);
return b;
}
public void marshal(Board b, OutputStream os) throws JAXBException {
Marshaller m = this.jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(b, os);
}
那么,有没有办法表示unmarshaller的文件结尾?或者,有更好的方法吗?
答案 0 :(得分:1)
即使有办法发出信号"文件结尾"对于unmarshaller,当两个或多个消息直接相继发送时,unmarshaller仍然有可能读入下一条消息。为防止这种情况发生,需要建立网络协议层,将发送/接收的字节逻辑分离为单独的消息。在下面的示例中,这个协议'已在writeMsg
和readMsg
方法中实施。请注意,这是一个简单的示例,假设所有消息都可以完全在内存中处理。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class NetworkMarshall {
private static final int NumberOfMsgs = 2;
public static void main(String[] args) {
Socket s = null;
try {
JAXBContext jc = JAXBContext.newInstance(NetworkMarshall.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Unmarshaller unmarshaller = jc.createUnmarshaller();
new Thread(new Receiver(unmarshaller)).start();
// Wait for socket server to start
Thread.sleep(500);
s = new Socket(InetAddress.getLocalHost(), 54321);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
for (int i = 0; i < NumberOfMsgs; i++) {
NetworkMarshall msg = new NetworkMarshall();
msg.setName("vanOekel" + i);
writeMsg(msg, marshaller, dos);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { s.close(); } catch (Exception ignored) {}
}
}
private static void writeMsg(NetworkMarshall msg, Marshaller marshaller, DataOutputStream dos) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
marshaller.marshal(msg, bout);
byte[] msgBytes = bout.toByteArray();
System.out.println("Sending msg: " + new String(msgBytes));
dos.writeInt(msgBytes.length);
dos.write(msgBytes);
dos.flush();
}
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return this.getClass().getName() + ": " + getName();
}
static class Receiver implements Runnable {
final Unmarshaller unmarshaller;
public Receiver(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public void run() {
ServerSocket ss = null;
Socket s = null;
try {
s = (ss = new ServerSocket(54321)).accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
for (int i = 0; i < NumberOfMsgs; i++) {
Object o = unmarshaller.unmarshal(readMsg(dis));
System.out.println("Received message " + i + ": " + o);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { ss.close(); } catch (Exception ignored) {}
try { s.close(); } catch (Exception ignored) {}
}
}
private ByteArrayInputStream readMsg(DataInputStream dis) throws Exception {
int size = dis.readInt();
byte[] ba = new byte[size];
dis.readFully(ba);
return new ByteArrayInputStream(ba);
}
}
}