我是编写基于客户端/服务器的应用程序的新手。服务器和客户端类都在线程中启动。在tcp上使用对象输出/输入流的新功能。从未有过序列化的乐趣。在我的应用程序中,我尝试使用对象输入/输出流,但看起来打开它们导致我的应用程序死亡。有趣的是,如果我评论两行:
outStream = new ObjectOutputStream(socket.getOutputStream());
inStream = new ObjectInputStream(socket.getInputStream());
连接工作正常,应用程序进入下一个面板等。但我仍然无法在整个套接字中发送任何对象。当我真的试图打开那些流。它仍然连接,但应用程序冻结。我有两个问题: 第一:使用序列化是否更好 第二:如果我可以使用对象流,我应该如何打开它们?我可以在服务器/客户端线程内完成吗?
感谢您的时间
以下是ClientApp的代码:
public void run()
{
while (true)
{
try // odswiezanie co sekunde
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
try // polaczenie
{
if (connecting)
{
socket = new Socket(hostIP, port);
JOptionPane.showMessageDialog(null, "Connection established!");
connected = true;
connecting = false;
frame.settingPanelForClient.bPlayerName.setText("Put the ships on your board!");
outStream = new ObjectOutputStream(socket.getOutputStream());
inStream = new ObjectInputStream(socket.getInputStream());
connectionEstablished(frame);
}
}
catch (UnknownHostException e)
{
JOptionPane.showMessageDialog(frame, "Unknown server!");
connected = false;
}
catch (IOException e)
{
JOptionPane.showMessageDialog(frame,"An Error occured while trying to connect to the server!");
e.getMessage();
e.printStackTrace();
connected = false;
}
catch (IllegalThreadStateException e)
{
e.printStackTrace();
}
try // odbior obiektow
{
if(connected)
{
while(!opponentIsReady){
System.out.println("wszedlem do connected!(klient) ");
System.out.println(opponentIsReady);
if(!opponentIsReady)
{
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
}
if(iAmReady && !opponentIsReady)
{
System.out.println("wszedlem do iAmReady i wysylam wiadomosc o gotowosci do klienta!");
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
outStream.writeObject(iAmReady);
outStream.flush();
}
if(opponentIsReady)
{
sendMap();
proceedToNextPanel(frame);
opponentIsReady = false;
}
}}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
答案 0 :(得分:0)
您是否使用Serializable界面作为地图对象?
如果您仍然在某一步骤冻结,可能是因为您尝试读取对象(来自服务器或客户端)并且您没有通过另一方发送它。当对象未被读取时,它将等待内容。
我不知道您的服务器是如何工作的,但是当oppenentReady
false
时,您会阅读两次回复。
if (inStream.readObject() != null) { if (inStream.readObject() instanceof Boolean) { //... } }如果这不是预期的行为,则应将其存储在局部变量中。
答案 1 :(得分:0)
再一次,这个我想要实现的smt(步骤)
1. user choose to open connection(he becomes a server and waits for a client
to connect) - done.
2. second user choose to connect(becomes a client and connects to the
second player(server) - done.
3. Both get message that the connection is established and they are moved
to the next Panel where they do specific operations - done.
4.When anyone of them finishes, I want to tell it to the second guy
(it is represented by a boolean local varable) - here comes the problem.
5. When both have finished, they should be moved to the next Panel where
they play.(before they start playing, Maps that they have set in the previous Panel
should be sent to each other.
如果我知道也许不知道如何发送这些信息,我可以处理下一步 但是在哪里发送代码因为它似乎在错误的地方。以下是客户端/服务器类的完整代码:
连接 - 按下按钮后,在另一个类中设置为true。
iAmready - 当玩家完成设置地图并且应该发送给对手时设置为true, 因为它在获得时将opponentIsReady设置为true来触发特定操作。
public class ClientApp implements Runnable
{
public static String hostIP = "127.0.0.1";
public static int port = 1000;
public static boolean connected = false;
public static boolean connecting = false;
public static boolean iAmReady = false;
public static boolean opponentIsReady = false;
public static Socket socket = null;
public static ObjectInputStream inStream;
public static ObjectOutputStream outStream;
public final Frame frame;
public static Map mapToGet;
public static Map mapToSend;
public ClientApp(Frame parent)
{
frame = parent;
mapToGet = new Map();
mapToSend = new Map();
}
@Override
public void run()
{
while (true)
{
try // odswiezanie co sekunde
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
try // polaczenie
{
if (connecting)
{
socket = new Socket(hostIP, port);
JOptionPane.showMessageDialog(null, "Connection established!");
connected = true;
connecting = false;
frame.settingPanelForClient.bPlayerName.setText("Put the ships on your board!");
connectionEstablished(frame);
}
}
catch (UnknownHostException e)
{
JOptionPane.showMessageDialog(frame, "Unknown server!");
connected = false;
}
catch (IOException e)
{
JOptionPane.showMessageDialog(frame,"An Error occured while trying to connect to the server!");
e.getMessage();
e.printStackTrace();
connected = false;
}
catch (IllegalThreadStateException e)
{
e.printStackTrace();
}
try // odbior obiektow
{
if(connected)
{
FileOutputStream out = new FileOutputStream("/tmp/message.ser");
outStream = new ObjectOutputStream(out);
FileInputStream in = new FileInputStream("/tmp/message.ser");
inStream = new ObjectInputStream(in);
while(!opponentIsReady){
System.out.println("wszedlem do connected!(klient) ");
System.out.println(opponentIsReady);
if(!opponentIsReady)
{
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
}
if(iAmReady && !opponentIsReady)
{
System.out.println("wszedlem do iAmReady i wysylam wiadomosc o gotowosci do klienta!");
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
outStream.writeObject(iAmReady);
outStream.flush();
}
if(opponentIsReady && iAmReady)
{
sendMap();
proceedToNextPanel(frame);
opponentIsReady = false;
}
}
inStream.close();
outStream.close();
in.close();
out.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
public static void connectionEstablished(Frame frame)
{
frame.remove(frame.connectPanel);
frame.getContentPane().add(frame.settingPanelForClient);
frame.validate();
frame.repaint();
}
public static void proceedToNextPanel(Frame frame)
{
frame.remove(frame.settingPanelForClient);
frame.getContentPane().add(frame.opponentsMove);
frame.validate();
frame.repaint();
}
public static Map getMap()
{
try
{
if (connected)
if (inStream.readObject() != null && inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
return mapToGet;
}
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
public static void sendMap()
{
if (connected)
if (mapToSend != null)
{
try
{
outStream.writeObject(mapToSend);
outStream.flush();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public class ServerApp implements Runnable
{
public static int port = 1000;
public static boolean connected = false;
public static boolean connecting = false;
public static boolean iAmReady = false;
public static boolean opponentIsReady = false;
public static Socket socket = null;
public static ServerSocket hostServer = null;
public static ObjectInputStream inStream;
public static ObjectOutputStream outStream;
public static Map mapToGet;
public static Map mapToSend;
final Frame frame;
public ServerApp(Frame parent)
{
frame = parent;
mapToGet = new Map();
mapToSend = new Map();
}
@Override
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e) {}
try
{
if (connecting)
{
hostServer = new ServerSocket(port);
socket = hostServer.accept();
connected = true;
connecting = false;
JOptionPane.showMessageDialog(null, "Connection Established!");
frame.settingPanelForServer.bPlayerName.setText("Put the ships on your board!");
connectionEstablished(frame);
}
}
catch (UnknownHostException e)
{
connected = connecting = false;
}
catch (IOException e)
{
connected = connecting = false;
}
try // odbior obiektow
{
if(connected)
{
while(!opponentIsReady){
System.out.println("wszedlem do connected(server)");
System.out.println(opponentIsReady);
if(!opponentIsReady)
{
inStream = new ObjectInputStream(socket.getInputStream());
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
}
if(iAmReady && !opponentIsReady)
{
System.out.println("wszedlem do iAmReady i wysylam wiadomosc o gotowosci do servera!");
outStream = new ObjectOutputStream(socket.getOutputStream());
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
outStream.writeObject(iAmReady);
outStream.flush();
}
if(opponentIsReady && iAmReady)
{
sendMap();
proceedToNextPanel(frame);
opponentIsReady = false;
}
}}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
public static void connectionEstablished(Frame frame)
{
frame.remove(frame.waitPanel);
frame.getContentPane().add(frame.settingPanelForServer);
frame.validate();
frame.repaint();
}
public static void proceedToNextPanel(Frame frame)
{
frame.remove(frame.settingPanelForServer);
frame.getContentPane().add(frame.playPanelForServer);
frame.validate();
frame.repaint();
}
public static Map getMap()
{
try
{
if (connected)
if (inStream.readObject() != null && inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
return mapToGet;
}
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
public static void sendMap()
{
if (connected)
if (mapToSend != null)
{
try
{
outStream.writeObject(mapToSend);
outStream.flush();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
答案 2 :(得分:0)
正如我之前所说,你不能对同一个对象多次使用readObject()。
实施例, 使用:
Object objectRead=inStream.readObject();
if (objectRead != null) {
if (objectRead instanceof Boolean) {
opponentIsReady = Boolean.valueOf(objectRead);
System.out.println(opponentIsReady);
} else if (objectRead instanceof Map) {
mapToGet = (Map) objectRead;
}
}
而不是:
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
我认为你不明白它是如何工作的: 当建立客户端/服务器连接时,您可以使用线程来读取或写入对象。
我为您提供了可以测试以了解其工作原理的代码:
ServerApp:
public class ServerApp implements Runnable { public static int port = 1000; public static boolean opponentIsReady = false; public static Socket socket = null; public static ServerSocket hostServer = null; public static ObjectInputStream inStream; public static ObjectOutputStream outStream; public static Map mapToGet; public static Map mapToSend; final Frame frame; private boolean connected = false; public ServerApp(Frame parent) { frame = parent; mapToGet = new Map(); mapToSend = new Map(); } @Override public void run() { // Server initialization side try { hostServer = new ServerSocket(port); JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish"); // Accept will wait until a client try to connect socket = hostServer.accept(); JOptionPane.showMessageDialog(null, "Connection Established!"); // Init streams when connection is etablished inStream = new ObjectInputStream(socket.getInputStream()); outStream = new ObjectOutputStream(socket.getOutputStream()); frame.settingPanelForServer.bPlayerName.setText("Put the ships on your board!"); connectionEstablished(frame); connected = true; } catch (IOException ex) { Logger.getLogger(ServerApp.class.getName()).log( Level.SEVERE, null, ex); } int x = 0; // The loop is made to send/receive all messages while (connected) { try { try { Thread.sleep(1000); } catch (InterruptedException ex) { Logger.getLogger(ServerApp.class.getName()).log( Level.SEVERE, null, ex); } Object o = String.format("I send you a message (%s)", x++); outStream.writeObject(o); Object response = inStream.readObject(); System.out.println("Response: " + response); } catch (IOException ex) { Logger.getLogger(ServerApp.class.getName()).log( Level.SEVERE, null, ex); connected = false; } catch (ClassNotFoundException ex) { Logger.getLogger(ServerApp.class.getName()).log( Level.SEVERE, null, ex); connected = false; } } System.err.println("Connection closed"); } public static void connectionEstablished(Frame frame) { frame.remove(frame.waitPanel); frame.getContentPane().add(frame.settingPanelForServer); frame.validate(); frame.repaint(); } public static void proceedToNextPanel(Frame frame) { frame.remove(frame.settingPanelForServer); frame.getContentPane().add(frame.playPanelForServer); frame.validate(); frame.repaint(); } public static Map getMap() { try { if (inStream.readObject() != null && inStream.readObject() instanceof Map) { mapToGet = (Map) inStream.readObject(); return mapToGet; } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } public static void sendMap() { if (mapToSend != null) { try { outStream.writeObject(mapToSend); outStream.flush(); } catch (IOException e) { e.printStackTrace(); } } } }
ClientApp:
public class ClientApp implements Runnable { public static String hostIP = "127.0.0.1"; public static int port = 1000; public static boolean connected = false; public static boolean connecting = true; public static boolean iAmReady = false; public static boolean opponentIsReady = false; public static Socket socket = null; public static ObjectInputStream inStream; public static ObjectOutputStream outStream; public final Frame frame; public static Map mapToGet; public static Map mapToSend; public ClientApp(Frame parent) { frame = parent; mapToGet = new Map(); mapToSend = new Map(); } @Override public void run() { try { // Client initialization side socket = new Socket(hostIP, port); // If the socket connection succeed it pass, else execption is thrown JOptionPane.showMessageDialog(null, "Connection Established!"); // Initialize streams outStream = new ObjectOutputStream(socket.getOutputStream()); inStream = new ObjectInputStream(socket.getInputStream()); frame.settingPanelForClient.bPlayerName.setText("Put the ships on your board!"); connectionEstablished(frame); connected=true; } catch (IOException ex) { Logger.getLogger(ClientApp.class.getName()).log( Level.SEVERE, null, ex); } // The loop will receive server message and send response while (connected) { try { Object serverMessage = inStream.readObject(); System.out.println("Server sent: " + serverMessage); Object myResponse = String.format("I received %s", serverMessage); outStream.writeObject(myResponse); } catch (IOException ex) { Logger.getLogger(ClientApp.class.getName()).log( Level.SEVERE, null, ex); connected=false; } catch (ClassNotFoundException ex) { Logger.getLogger(ClientApp.class.getName()).log( Level.SEVERE, null, ex); connected=false; } } System.err.println("Connection closed"); } public static void connectionEstablished(Frame frame) { frame.remove(frame.connectPanel); frame.getContentPane().add(frame.settingPanelForClient); frame.validate(); frame.repaint(); } public static void proceedToNextPanel(Frame frame) { frame.remove(frame.settingPanelForClient); frame.getContentPane().add(frame.opponentsMove); frame.validate(); frame.repaint(); } public static Map getMap() { try { if (connected) { if (inStream.readObject() != null && inStream.readObject() instanceof Map) { mapToGet = (Map) inStream.readObject(); return mapToGet; } } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } public static void sendMap() { if (connected) { if (mapToSend != null) { try { outStream.writeObject(mapToSend); outStream.flush(); } catch (IOException e) { e.printStackTrace(); } } } } }