Java套接字 - 接收但不发送的内容!

时间:2010-12-05 00:31:17

标签: java sockets

我一直在尝试调试这个2个小时,我无法解释它。 我有一个服务器和一个客户端。 (服务器管理一些拍卖)。

会发生什么:

  1. 客户端请求一些东西,服务器发回数据,客户端收到它就好了。

  2. 客户端向服务器发送内容,服务器更新一些数据。

  3. 客户端发出与第一次相同的请求(1.),服务器发回更新的请求 数据,但客户端不接收新的更新数据,而是接收旧数据(因为它在第一个请求中得到它(1.)。

  4. 正在发送的数据只是一个带有两个List-s的Java Bean。 代码:

     // CLIENT CLASS
    // creates socket, sends and listens on the socket
    // listening is done on a separate thread
    public class ServerConnector {
    
    private Socket socket = null;
    private ObjectOutputStream out = null;
    private Display display;
    private ServerListener listener;
    public ServerConnector(Display display) {
        this.display = display;
            try {
                socket = new Socket("localhost",33333);
                out = new ObjectOutputStream(socket.getOutputStream());
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            listener = new ServerListener(socket, display);
            new Thread(listener).start();
    
    
    }
    
    
    
    public void sendRequest(Request request) {
        try {
            out.writeObject(request);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
    
    class ServerListener implements Runnable {
        private Socket socket;
        private ObjectInputStream in = null;
        private Display display;
        public ServerListener(Socket socket,Display display) {
            this.socket = socket;
            this.display = display;
            try {
                in = new ObjectInputStream(socket.getInputStream());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            Response response =null;
    
            try {
                while ((response = (Response)in.readObject()) != null) {
                    if (response.getCars().size() > 0) {
                        display.showAvailableCars(response.getCars());
                    }
                    if(response.getAucs().size() > 0) {
                        List<Auction> auctionz  = response.getAucs();//HERE 1st time it gets the GOOD data, 2nd time should get UPDATED DATA but instead receives the OLD DATA (same as 1st time).
                        display.showOpenAuctions(auctionz);
                    }
                    response = null;
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
    }
    
    }
    //CLIENT CLASS
    // controls when something should be sent, and print out responses
    public class Display {
    Scanner console = new Scanner(System.in);
    ServerConnector server = new ServerConnector(this);
    List<Car> cars;
    List<Auction> aucs;
    
    public void show() {
        int opt = 0;
            System.out.println("1. Show available cars for auction.");
            System.out.println("2. Show open auctions.");
            opt = console.nextInt();
            Request request = new Request();
            if (opt == 1)
                request.setRequest(Request.GET_CARS);
            if (opt == 2) {
                request.setRequest(Request.GET_OPEN_AUCTIONS);
            }
            server.sendRequest(request);
    
        }
    
    
    public void showAvailableCars(List<Car> cars) {
        int i = 0;
        for (Car c : cars ){
            i++;
            System.out.println(i +". " + c.getMaker() + " " + c.getModel() + " price: " + c.getPrice());
        }
        System.out.println("Select car to open Auction for:");
        int selectedCar = console.nextInt();
        if (selectedCar != 0) {
            if (selectedCar <= cars.size()) {
                Request request= new Request();
                request.setRequest(Request.OPEN_AUCTION);
                Car c = cars.get(selectedCar-1);
                request.setCar(c);
                server.sendRequest(request);
            }
        }
        show();
    }
    
    
    public void setCars(List<Car> cars) {
        this.cars = cars;
    
    }
    
    
    public void showOpenAuctions(List<Auction> aucs2) {
        int i = 0;
        for (Auction auc : aucs2) {
            i++;
            System.out.println(i+ ". " + auc.getCar().getModel() + " " + auc.getCar().getMaker() + " last price: " + auc.getPrice());
        }
        System.out.println("You can now make offers");
        System.out.println("Input auction number:");
        int selectedAuction = 0;
        selectedAuction = console.nextInt();
        if (selectedAuction > 0 && selectedAuction <= aucs2.size()) {
            System.out.println("Offer new price:");
            int price = console.nextInt();
            Request request= new Request();
            request.setRequest(Request.MAKE_OFFER);
            request.setAuctionId(aucs2.get(selectedAuction-1).getId());
            request.setPrice(price);
            server.sendRequest(request);
        }
        show();
    
    }
    
    
    public void setOpenAuctions(List<Auction> aucs2) {
        this.aucs = aucs2;
    
    }
    
    }
    // SERVER CLASS : send and receives
    public class ClientManager implements Runnable {
    
    private AuctionManager manager = new AuctionManagerImpl();
    private Socket client;
    private ObjectInputStream in = null;
    private ObjectOutputStream out = null;
    
    
    public ClientManager(Socket socket) {
        this.client = socket;
         try {
              in = new ObjectInputStream(client.getInputStream());
              out = new ObjectOutputStream(client.getOutputStream());
         } catch(Exception e1) {
                 try {
                     e1.printStackTrace();
                    client.close();
           }catch(Exception e) {
                   System.out.println(e.getMessage());
                 }
                 return;
             }
    }
    
    @Override
    public void run() {
        Request req = null;
        try {
                while ((req = (Request)in.readObject()) != null) {
                    if (req.getRequest() != null) {
                        if (req.getRequest().equals(Request.GET_CARS)) {
                            Response response = new Response();
                            response.setCars(manager.getAvailableCars());
                            out.writeObject(response);
                            continue;
                        }
    
                        if (req.getRequest().equals(Request.OPEN_AUCTION)) {
                            manager.openAuction(req.getCar());
                            continue;
                        }
    
                        if (req.getRequest().equals(Request.GET_OPEN_AUCTIONS)) {
                            Response response = new Response();
                            response.setAucs(manager.getHoldedAuctions()); //this line ALWAYS sends to the client GOOD, UPDATED DATA
    
                            out.writeObject(response);
                            out.flush();
                            continue;
                        }
                        if (req.getRequest().equals(Request.MAKE_OFFER)) {
                            Auction auction = manager.getOpenAuction(req.getAuctionId());
                            manager.updateAuction(auction, req.getPrice(),client.getRemoteSocketAddress().toString());
                            continue;
                        }
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
    
    }
    

3 个答案:

答案 0 :(得分:3)

可能是因为您使用的是ObjectOutputStreams。请记住,ObjectOutputStreams将缓存写入它们的所有对象,以便将来再次写入相同的对象时,它可以编写反向引用而不是重写整个对象。在编写对象图时,这是必要的。

您的代码片段:

if (req.getRequest().equals(Request.GET_CARS)) {
    Response response = new Response();
    response.setCars(manager.getAvailableCars());
    out.writeObject(response);
    continue;
}

正在编写manager.getAvailableCars()返回的对象。下一次收到请求时,会写入相同的对象(但现在具有不同的内容) - 但ObjectOutputStream不知道新内容,因此它只写了一个反向引用。另一端的ObjectInputStream看到后引用并返回它上次读取的同一对象,即原始数据。

您可以在每次回复后致电ObjectOutputStream.reset()来解决此问题。这将清除流的缓存。

答案 1 :(得分:2)

请参阅ObjectOutputStream.writeUnshared()和.reset()。

答案 2 :(得分:0)

确定。我刚刚找到了解决方案。 从这里http://java.sun.com/developer/technicalArticles/ALT/sockets/

对象序列化陷阱

使用对象序列化时,请务必记住ObjectOutputStream维护一个哈希表,将写入流的对象映射到句柄。当第一次将对象写入流时,其内容将被复制到流中。但是,后续写入会导致正在写入流的对象的句柄。这可能会导致一些问题:

如果将对象写入流然后再次修改和写入,则在对流进行反序列化时将不会注意到这些修改。同样,原因是后续写入会导致写入句柄,但修改后的对象不会复制到流中。要解决此问题,请调用ObjectOutputStream.reset方法,该方法丢弃已发送对象的内存,以便后续写入将对象复制到流中。 将大量对象写入ObjectOutputStream后,可能会抛出OutOfMemoryError。这样做的原因是哈希表维护对应用程序可能无法访问的对象的引用。只需调用ObjectOutputStream.reset方法将对象/句柄表重置为初始状态即可解决此问题。在此调用之后,所有先前编写的对象都有资格进行垃圾回收。 reset方法将流状态重置为刚刚构造的流状态。在序列化对象时,可能不会调用此方法。对此方法的不适当调用会导致IOException。