Java 客户端服务器、对象输入/输出、死锁

Java 客户端服务器、对象输入/输出、死锁,java,object,input,output,tcpclient,Java,Object,Input,Output,Tcpclient,我对编写基于客户端/服务器的应用程序相当陌生。服务器和客户端类都在线程中启动。在tcp上使用对象输出/输入流也是一种新方法。从未享受过序列化的乐趣。在我的应用程序中,我试图使用对象输入/输出流,但打开它们似乎会导致我的应用程序死机。有趣的是,如果我评论两行: outStream = new ObjectOutputStream(socket.getOutputStream()); inStream = new ObjectInputStream(socket.getInputStream());

我对编写基于客户端/服务器的应用程序相当陌生。服务器和客户端类都在线程中启动。在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();
        }

    }
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(); } } } } } 您是否使用映射对象的接口

如果您仍在某个步骤中冻结,可能是因为您尝试读取对象(从服务器或客户端),而您没有从另一端发送它。当对象未被读取时,它将等待内容

我不知道您的服务器是如何工作的,但当
oppenentReady
false
时,您会读取两次响应。 if(inStream.readObject()!=null){ if(inStream.readObject()实例为布尔值){ //... } }
如果这不是预期的行为,您应该将其存储在局部变量中。

再一次,这是我想要实现的smt(分步骤)

如果我不知道如何发送这些信息,我可以处理下一步的工作 但是在哪里放置发送代码,因为它似乎位于错误的位置。以下是客户端/服务器类的完整代码:

连接-按下按钮后,在其他类中设置为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();
            }
        }
}
}


}

正如我前面所说,同一对象不能多次使用readObject()

例如, 使用:

而不是:

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();
    }
}
我想你不明白它是怎么工作的: 当客户机/服务器连接被删除时,您可以使用线程来读取或写入对象

我为您提供了可以测试的代码,以了解其工作原理:

服务器应用程序:

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(); } } } } 公共类ServerApp实现可运行{ 公共静态int端口=1000; public static boolean opponentIsReady=false; 公共静态套接字=空; publicstaticserversockethostserver=null; 公共静态对象流内输入流; 公共静态对象输出流扩展; 公共静态地图; 公共静态地图; 最终框架; 私有布尔连接=假; 公共服务器应用程序(帧父级){ 帧=父帧; mapToGet=newmap(); mapToSend=newmap(); } @凌驾 公开募捐{ //服务器初始化端 试一试{ hostServer=新服务器套接字(端口); showMessageDialog(框架,“等待对手完成”); //Accept将等待客户端尝试连接 socket=hostServer.accept(); showMessageDialog(null,“已建立连接!”); //初始化连接时流 inStream=newObjectInputStream(socket.getInputStream()); outStream=newObjectOutputStream(socket.getOutputStream()); frame.settingPanelForServer.bPlayerName.setText(“把船放到你的船上!”); 建立连接(框架); 连接=真; }捕获(IOEX异常){ Logger.getLogger(ServerApp.class.getName()).log( 级别(严重、空、ex); } int x=0; //循环用于发送/接收所有消息 同时(连接){ 试一试{ 试一试{ 睡眠(1000); }捕获(中断异常例外){ Logger.getLogger(ServerApp.class.getName()).log( 级别(严重、空、ex); } Object o=String.format(“我向您发送了一条消息(%s)”,x++); 外扩写对象(o); 对象响应=inStream.readObject(); System.out.println(“响应:+Response”); }捕获(IOEX异常){ Logger.getLogger(ServerApp.class.getName()).log( 级别(严重、空、ex); 连接=错误; }捕获(ClassNotFoundException ex){ Logger.getLogger(ServerApp.class.getName()).log( 级别(严重、空、ex); 连接=错误; } } System.err.println(“连接关闭”); } 已建立公用静态无效连接(框架){ 框架。移除(框架。面板); frame.getContentPane().add(frame.settingPanelForServer); frame.validate(); frame.repaint(); } 公共静态void proceedToNextPanel(框架){ frame.remove(frame.settingPanelForServer); frame.getContentPane().add(frame.playbanelforserver); frame.validate(); frame.repaint(); } 公共静态映射getMap(){ 试一试{ if(inStream.readObject()!=null&&inStream.readObject()映射实例){ mapToGet=(Map)inStream.readObject(); 返回映射集; } }catch(classnotfounde异常){ e、 printStackTrace(); }捕获(IOE异常){ e、 printStackTrace(); } 返回null; } 公共静态void sendMap(){ if(mapToSend!=null){ 试一试{ outStream.writeObject(mapToSend); 突出
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();
    }
}
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(); } } } } 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(); } } } } }