【问题标题】:Unmarshalling Hangs on Open Socket打开套接字上的解组挂起
【发布时间】:2014-04-28 17:33:25
【问题描述】:

我编写了一个可运行的网络类,它在套接字上侦听并解组输入。它还可以使用编组对象写入套接字。由于套接字保持打开状态(以便以后在客户端和主机之间进行通信)而出现问题 - 这会导致输入流的解组挂起。我已经尝试从发送方编写 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();
    }
} 

这是我的 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);
}

那么,有没有办法为解组器表示文件结束?或者,有没有更好的方法来做到这一点?

【问题讨论】:

    标签: java multithreading sockets marshalling unmarshalling


    【解决方案1】:

    即使有一种方法可以向解组器发出“文件结束”信号,但当两个或多个消息相继发送时,解组器仍然有机会读入下一条消息。为了防止这种情况发生,需要有一个网络协议层在逻辑上将发送/接收的字节分成单独的消息。在下面的示例中,此“协议”在writeMsgreadMsg 方法中实现。请注意,这是一个假设所有消息都可以完全在内存中处理的简单示例。

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

    【讨论】:

      猜你喜欢
      • 2011-01-19
      • 1970-01-01
      • 2019-10-14
      • 2016-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      • 2014-04-12
      相关资源
      最近更新 更多