我正在尝试将一些 xml 从客户端发送到服务器,并让服务器在接收到数据后将消息发送回客户端。如果它只是发送 xml,那么它运行顺利,但是当客户端期待响应时,它会永远阻塞。我从另一篇文章中读到解组关闭套接字,所以我使用了 filterStream 但它似乎并没有解决问题。有任何想法吗?
这是我的代码:
客户
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.net.Socket;
import javax.xml.bind.annotation.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Client {
public static void main(String args[]) throws JAXBException, IOException {
JAXBContext context = JAXBContext.newInstance(Product.class);
Socket sock = new Socket("localhost", 4000);
Marshaller m = context.createMarshaller();
BufferedReader br = new BufferedReader(new InputStreamReader(new MyInputStream(sock.getInputStream())));
PrintStream ps = new PrintStream(sock.getOutputStream());
Product object = new Product();
object.setCode("WI1");
object.setName("Widget Number One");
object.setPrice(BigDecimal.valueOf(300.00));
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(Marshaller.JAXB_FRAGMENT, true);
System.out.println("Data Sent");
m.marshal(object, ps);
System.out.println("Waiting for response from server");
String msg = br.readLine(); // runs smoothly if client doesn't wait for response
if (msg != null) {
System.out.println(msg);
}
br.close();
sock.close();
}
}
@XmlRootElement
class Product {
private String code;
private String name;
private BigDecimal price;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
服务器:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.math.BigDecimal;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
public class Server {
public static void main(String a[]) throws IOException, JAXBException {
Socket sock;
ServerSocket servsock = new ServerSocket(4000, 1);
while (true) {
sock = servsock.accept();
new WorkerThread(sock).start();
}
}
}
class WorkerThread extends Thread {
Socket sock;
WorkerThread(Socket s) {
sock = s;
}
public void run() {
try {
PrintStream out = new PrintStream(sock.getOutputStream()); // to send ack back to client;
BufferedReader in = new BufferedReader(new InputStreamReader(new MyInputStream(sock.getInputStream())));;
JAXBContext context = JAXBContext.newInstance(Product.class);
Unmarshaller um = context.createUnmarshaller();
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource ss = new StreamSource(in);
XMLStreamReader xsr = xif.createXMLStreamReader(ss);
xsr.nextTag();
JAXBElement<Product> xmlToJava = um.unmarshal(xsr, Product.class);
Product product = xmlToJava.getValue();
System.out.println("closing");
xsr.close();
System.out.println(product.getName());
System.out.println(product.getCode());
System.out.println(product.getPrice());
out.println("data recieved");
out.flush();
} catch (IOException ex) {
Logger.getLogger(WorkerThread.class.getName()).log(Level.SEVERE, null, ex);
} catch (JAXBException ex) {
Logger.getLogger(WorkerThread.class.getName()).log(Level.SEVERE, null, ex);
} catch (XMLStreamException ex) {
Logger.getLogger(WorkerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class MyInputStream extends FilterInputStream {
public MyInputStream(InputStream in) {
super(in);
}
@Override
public void close() {
}
}
@XmlRootElement
class Product {
private String code;
private String name;
private BigDecimal price;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}