Java 解组挂在打开的套接字上

Java 解组挂在打开的套接字上,java,multithreading,sockets,marshalling,unmarshalling,Java,Multithreading,Sockets,Marshalling,Unmarshalling,我编写了一个可运行的网络类,它监听套接字并解组输入。它还可以使用封送对象写入套接字。出现问题的原因是套接字保持打开状态(以便允许客户端和主机之间的后续通信)——这会导致输入流的解组挂起。我已尝试从发送方编写XMLStreamConstants.END_文档,但这会导致错误解组而不是挂起。以下是网络类的一些代码: @Override public void update(Observable o, Object arg) { try { if(!this.updatedBy

我编写了一个可运行的网络类,它监听套接字并解组输入。它还可以使用封送对象写入套接字。出现问题的原因是套接字保持打开状态(以便允许客户端和主机之间的后续通信)——这会导致输入流的解组挂起。我已尝试从发送方编写XMLStreamConstants.END_文档,但这会导致错误解组而不是挂起。以下是网络类的一些代码:

@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();
    }
} 
以下是我的marshall处理程序的代码:

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);
}

那么,有没有一种方式可以表示解编程序的文件结束?或者,有更好的方法吗?

即使有方法向解组器发出“文件结束”的信号,当两条或多条消息直接互相发送时,解组器仍有可能读入下一条消息。为了防止这种情况发生,需要有一个网络协议层,在逻辑上将发送/接收的字节分隔成单独的消息。在下面的示例中,此“协议”在
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);
    }
}
}
import java.io.ByteArrayInputStream;
导入java.io.ByteArrayOutputStream;
导入java.io.DataInputStream;
导入java.io.DataOutputStream;
导入java.net.InetAddress;
导入java.net.ServerSocket;
导入java.net.Socket;
导入javax.xml.bind.JAXBContext;
导入javax.xml.bind.Marshaller;
导入javax.xml.bind.Unmarshaller;
导入javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
公共类网络{
私有静态最终int NumberOfMsgs=2;
公共静态void main(字符串[]args){
套接字s=null;
试一试{
JAXBContext jc=JAXBContext.newInstance(NetworkMarshall.class);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
Unmarshaller Unmarshaller=jc.createUnmarshaller();
新线程(新接收器(解组器)).start();
//等待套接字服务器启动
睡眠(500);
s=新套接字(InetAddress.getLocalHost(),54321);
DataOutputStream dos=新的DataOutputStream(s.getOutputStream());
对于(int i=0;i