Java套接字-接收但不是发送的内容!
我已经试着调试这两个小时了,我就是解释不了。 我有一个服务器和一个客户端。(服务器管理一些拍卖) 发生了什么:Java套接字-接收但不是发送的内容!,java,sockets,Java,Sockets,我已经试着调试这两个小时了,我就是解释不了。 我有一个服务器和一个客户端。(服务器管理一些拍卖) 发生了什么: 客户机请求一些东西,服务器发送回数据,客户机接收到的数据很好 客户端向服务器发送一些数据,服务器更新一些数据 客户端发出与第一次(1)相同的请求,服务器发回更新的 数据,但客户端不接收新的更新数据,而是接收旧数据(在第一个请求(1.)中获得) 正在发送的数据只是一个带有两个List-s的javabean。 以及守则: // CLIENT CLASS // creates socket
// 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();
}
}
}
//客户端类
//创建套接字、发送和侦听套接字
//监听是在一个单独的线程上完成的
公共类服务器连接器{
私有套接字=空;
private ObjectOutputStream out=null;
私人显示器;
私有服务器侦听器;
公用服务器连接器(显示器){
this.display=显示;
试一试{
套接字=新套接字(“localhost”,33333);
out=newObjectOutputStream(socket.getOutputStream());
}捕获(未知后异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
listener=新的ServerListener(套接字,显示);
新线程(侦听器).start();
}
公共无效发送请求(请求){
试一试{
out.writeObject(请求);
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
类ServerListener实现可运行{
专用插座;
私有ObjectInputStream in=null;
私人显示器;
公共服务器侦听器(套接字、显示){
this.socket=socket;
this.display=显示;
试一试{
in=newObjectInputStream(socket.getInputStream());
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
@凌驾
公开募捐{
响应=空;
试一试{
while((response=(response)in.readObject())!=null){
if(response.getCars().size()>0){
display.showAvailableCars(response.getCars());
}
if(response.getAucs().size()>0){
List auctionz=response.getAucs();//这里第一次得到好数据时,第二次应该得到更新的数据,但收到的是旧数据(与第一次相同)。
展示。展示公开拍卖(auctionz);
}
响应=空;
}
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}catch(classnotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
}
//客户端类
//控制何时发送内容,并打印响应
公开课展示{
扫描仪控制台=新扫描仪(System.in);
ServerConnector服务器=新的ServerConnector(此);
列出车辆清单;
列出拍卖价格;
公开展览({
int opt=0;
System.out.println(“1.展示可供拍卖的汽车。”);
System.out.println(“2.显示公开拍卖”);
opt=console.nextInt();
请求=新请求();
如果(opt==1)
request.setRequest(request.GET_CARS);
如果(opt==2){
request.setRequest(request.GET_OPEN_拍卖);
}
sendRequest(请求);
}
公共空间展示车(列出车辆){
int i=0;
用于(c车:汽车){
i++;
System.out.println(i++“+c.getMaker()+”+c.getModel()+“price:+c.getPrice());
}
System.out.println(“选择要公开拍卖的汽车:”);
int selectedCar=console.nextInt();
如果(selectedCar!=0){
如果(selectedCar 0&&SelectedAction请参见ObjectOutputStream.writeUnshared()和.reset().这可能是因为您使用的是ObjectOutputStreams
。请记住,ObjectOutputStreams
将缓存写入其中的所有对象,以便将来再次写入同一对象时,它可以写回引用,而不是重新写入整个对象。这在写入对象图时是必需的
您的代码片段:
if (req.getRequest().equals(Request.GET_CARS)) {
Response response = new Response();
response.setCars(manager.getAvailableCars());
out.writeObject(response);
continue;
}
正在写入由管理器.getAvailableCars()返回的对象。
。下次收到请求时,将使用相同的对象(但现在使用不同的内容)已写入-但ObjectOutputStream
不知道新内容,因此它只写回引用。另一端的ObjectInputStream
看到回引用并返回上次读取的相同对象,即原始数据
您可以通过在每次响应后调用ObjectOutputStream.reset()
来修复此问题。这将清除流的缓存。好的。我刚刚找到了解决方案。
从这里开始:
对象序列化陷阱
在处理对象序列化时,请务必记住,ObjectOutputStream维护一个哈希表,将写入流中的对象映射到句柄。当对象第一次写入流时,其内容将复制到流中。但是,随后的写入会导致对象的句柄丢失g写入流。这可能会导致两个问题:
如果将对象写入流,然后进行第二次修改和写入,则在反序列化流时不会注意到修改。同样,原因是后续写入会导致写入句柄,但修改后的对象不会复制到流中。若要解决此问题,请调用ObjectOutputStrea