【问题标题】:Server and Client using Sockets使用套接字的服务器和客户端
【发布时间】:2015-11-29 05:48:51
【问题描述】:

是否有任何使用套接字但具有发送和获取方法的服务器和客户端的示例?我正在做这个网络战舰程序,几乎完成了,但无法让服务器和客户端工作。我做了一个只发送字符串的聊天程序,但是这次我需要发送对象。我已经很沮丧了,所以有没有源代码已经有了这个。

这是客户端的代码...您将如何修改它以允许发送对象?我还需要监听传入的对象并立即处理它们。

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SimpleChat extends JFrame {
  private Socket         communicationSocket   = null;
  private PrintWriter    outStream             = null;
  private BufferedReader inStream              = null;
  private Boolean        communicationContinue = true;
  private String         disconnectString      = "disconnect764*#$1";
  private JMenuItem      disconnectItem;
  private JTextField     displayLabel;
  private final Color    colorValues[]         = { Color.black, Color.blue, Color.red, Color.green };

  // set up GUI
  public SimpleChat() {
    super("Simple Chat");

    // set up File menu and its menu items
    JMenu fileMenu = new JMenu("File");
    fileMenu.setMnemonic('F');

    // set up Activate Server menu item
    JMenuItem serverItem = new JMenuItem("Activate Server");
    serverItem.setMnemonic('S');
    fileMenu.add(serverItem);
    serverItem.addActionListener(new ActionListener() { // anonymous inner class
                // display message dialog when user selects About...
                public void actionPerformed(ActionEvent event) {
                  setUpServer();
                }
              } // end anonymous inner class
              ); // end call to addActionListener

    // set up Activate Client menu item
    JMenuItem clientItem = new JMenuItem("Activate Client");
    clientItem.setMnemonic('C');
    fileMenu.add(clientItem);
    clientItem.addActionListener(new ActionListener() { // anonymous inner class
                // display message dialog when user selects About...
                public void actionPerformed(ActionEvent event) {
                  setUpClient();
                }
              } // end anonymous inner class
              ); // end call to addActionListener

    // set up Activate Client menu item
    disconnectItem = new JMenuItem("Disconnect Client/Server");
    disconnectItem.setMnemonic('D');
    disconnectItem.setEnabled(false);
    fileMenu.add(disconnectItem);
    disconnectItem.addActionListener(new ActionListener() { // anonymous inner
                    // class
                    // display message dialog when user selects About...
                    public void actionPerformed(ActionEvent event) {
                      disconnectClientServer(true);
                    }
                  } // end anonymous inner class
                  ); // end call to addActionListener

    // set up About... menu item
    JMenuItem aboutItem = new JMenuItem("About...");
    aboutItem.setMnemonic('A');
    fileMenu.add(aboutItem);
    aboutItem.addActionListener(new ActionListener() { // anonymous inner class
               // display message dialog when user selects About...
               public void actionPerformed(ActionEvent event) {
                 JOptionPane.showMessageDialog(SimpleChat.this, "This is an example\nof using menus", "About",
                                               JOptionPane.PLAIN_MESSAGE);
               }
             } // end anonymous inner class
             ); // end call to addActionListener

    // set up Exit menu item
    JMenuItem exitItem = new JMenuItem("Exit");
    exitItem.setMnemonic('x');
    fileMenu.add(exitItem);
    exitItem.addActionListener(new ActionListener() { // anonymous inner class
              // terminate application when user clicks exitItem
              public void actionPerformed(ActionEvent event) {
                disconnectClientServer(true);
                System.exit(0);
              }
            } // end anonymous inner class
            ); // end call to addActionListener

    // create menu bar and attach it to MenuTest window
    JMenuBar bar = new JMenuBar();
    setJMenuBar(bar);
    bar.add(fileMenu);

    // set up label to display text
    displayLabel = new JTextField("Sample Text", SwingConstants.CENTER);
    displayLabel.setForeground(colorValues[0]);
    displayLabel.setFont(new Font("Serif", Font.PLAIN, 72));
    displayLabel.addActionListener(new ActionListener() { // anonymous inner
                  // class
                  // display message dialog when user selects About...
                  public void actionPerformed(ActionEvent event) {
                    sendData();
                  }
                } // end anonymous inner class
                ); // end call to addActionListener

    getContentPane().setBackground(Color.CYAN);
    getContentPane().add(displayLabel, BorderLayout.CENTER);

    setSize(500, 200);
    setVisible(true);

  } // end constructor

  public static void main(String args[]) {
    final SimpleChat application = new SimpleChat();
    application.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        application.disconnectClientServer(true);
        System.exit(0);
      }
    });

    // application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
  }

  public void setCommunicationSocket(Socket sock) {
    communicationSocket = sock;
    communicationContinue = true;
    disconnectItem.setEnabled(true);
  }

  public void setOutStream(PrintWriter out) {
    outStream = out;
  }

  public void setInStream(BufferedReader in) {
    inStream = in;
  }

  public void setUpServer() {
    ServerThread st = new ServerThread(this);
    st.start();
  }

  public void setUpClient() {
    ClientThread st = new ClientThread(this);
    st.start();
  }

  public void disconnectClientServer(Boolean sendMessage) {
    if (communicationSocket == null)
      return;

    try {
      // shut down socket read loop
      communicationContinue = false;
      disconnectItem.setEnabled(false);

      // send notification to other end of socket
      if (sendMessage == true)
        outStream.println(disconnectString);

      // sleep to let read loop shut down
      Thread t = Thread.currentThread();
      try {
        t.sleep(500);
      } catch (InterruptedException ie) {
        return;
      }

      outStream.close();
      inStream.close();
      communicationSocket.close();
    } catch (IOException e) {
      System.err.println("Stream Read Failed.");
      JOptionPane.showMessageDialog(SimpleChat.this, "Disconnection Failed", "SimpleChat", JOptionPane.PLAIN_MESSAGE);
      return;
    } finally {
      communicationSocket = null;
    }
  }

  public void sendData() {
    if (communicationSocket != null) {
      String data = displayLabel.getText();
      outStream.println(data);
    }
  }

  public void getData() {
    String inputLine;
    try {
      while (communicationContinue == true) {
        communicationSocket.setSoTimeout(100);
        // System.out.println ("Waiting for Connection");
        try {
          while (((inputLine = inStream.readLine()) != null)) {
            System.out.println("From socket: " + inputLine);
            if (inputLine.equals(disconnectString)) {
              disconnectClientServer(false);
              return;
            }
            displayLabel.setText(inputLine);
          }
        } catch (SocketTimeoutException ste) {
          // System.out.println ("Timeout Occurred");
        }
      } // end of while loop
      System.out.println("communication is false");
    } catch (IOException e) {
      System.err.println("Stream Read Failed.");
      JOptionPane.showMessageDialog(SimpleChat.this, "Input Stream read failed", "SimpleChat",
                                    JOptionPane.PLAIN_MESSAGE);
      return;
    }
  }
}

class ServerThread extends Thread {
  private SimpleChat sc;
  private JTextField display;

  public ServerThread(SimpleChat scParam) {
    sc = scParam;
  }

  public void run() {
    ServerSocket connectionSocket = null;

    try {
      connectionSocket = new ServerSocket(10007);
    } catch (IOException e) {
      System.err.println("Could not listen on port: 10007.");
      JOptionPane.showMessageDialog(sc, "Could not listen on port: 10007", "Server", JOptionPane.PLAIN_MESSAGE);
      return;
    }

    JOptionPane.showMessageDialog(sc, "Server Socket is now activated", "Server", JOptionPane.PLAIN_MESSAGE);

    Socket communicationSocket = null;

    try {
      communicationSocket = connectionSocket.accept();
    } catch (IOException e) {
      System.err.println("Accept failed.");
      JOptionPane.showMessageDialog(sc, "Accept failed", "Server", JOptionPane.PLAIN_MESSAGE);
      return;
    }

    JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Server", JOptionPane.PLAIN_MESSAGE);

    try {
      PrintWriter out = new PrintWriter(communicationSocket.getOutputStream(), true);
      BufferedReader in = new BufferedReader(new InputStreamReader(communicationSocket.getInputStream()));

      sc.setCommunicationSocket(communicationSocket);
      sc.setOutStream(out);
      sc.setInStream(in);

      connectionSocket.close();

      sc.getData();

    } catch (IOException e) {
      System.err.println("Accept failed.");
      JOptionPane.showMessageDialog(sc, "Creation of Input//Output Streams failed", "Server", JOptionPane.PLAIN_MESSAGE);
      return;
    }
  }
}

class ClientThread extends Thread {
  private SimpleChat sc;

  public ClientThread(SimpleChat scParam) {
    sc = scParam;
  }

  public void run() {
    Socket echoSocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    String ipAddress = "127.0.0.1";

    try {
      echoSocket = new Socket(ipAddress, 10007);
      out = new PrintWriter(echoSocket.getOutputStream(), true);
      in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
    } catch (UnknownHostException e) {
      System.err.println("Don't know about host: " + ipAddress);
      JOptionPane.showMessageDialog(sc, "Don't know about host: " + ipAddress, "Client", JOptionPane.PLAIN_MESSAGE);
      return;
    } catch (IOException e) {
      System.err.println("Couldn't get I/O for " + "the connection to: " + ipAddress);
      JOptionPane.showMessageDialog(sc, "Couldn't get I/O for the connection to: " + ipAddress, "Client",
                                    JOptionPane.PLAIN_MESSAGE);
      return;
    }
    JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Client", JOptionPane.PLAIN_MESSAGE);

    sc.setCommunicationSocket(echoSocket);
    sc.setOutStream(out);
    sc.setInStream(in);

    sc.getData();
  }
}

【问题讨论】:

  • 如果没有所有额外的代码,这会更清楚
  • 请参阅this stackoverflow answer 以获取有关将对象序列化和后续通过套接字发送/获取而不使用 RMI 链接在一起的教程的参考。

标签: java sockets


【解决方案1】:

我建议您阅读 java 序列化。有一个例子here。基本上,有内置的序列化支持。你的类需要实现Serializable。然后你使用 ObjectOutputStreamObjectInputStream 来写对象。

【讨论】:

    【解决方案2】:

    建议您使用可以保护您免受容易出错的低级套接字编程的库。

    对于 C++,请使用 Boost (http://www.boost.com) 或 ACE (http://www.cs.wustl.edu/~schmidt/ACE.html)

    对于 Java,我只找到了一个关于接受器模式 http://www.hillside.net/plop/plop99/proceedings/Fernandez3/RACPattern.PDF 的文档 但我确信某处有一个实现

    【讨论】:

      【解决方案3】:

      你在正确的轨道上。聊天程序是开始学习套接字的好地方。

      您想要的是使用 ObjectOutputStream 和 ObjectInputStream 类。您只需使用这些过滤器包装您的输入流/输出流。 ObjectOutputStream 有 writeObject() 方法,ObjectInputStream 有对应的 readObject() 方法。

      大多数序列化示例显示了读取和写入对象到文件,但同样可以使用套接字流来完成。见http://www.acm.org/crossroads/xrds4-2/serial.html

      【讨论】:

        【解决方案4】:

        我没有费心阅读你成堆的代码,但通常你不能直接通过网络发送对象。网络通信只是位和字节。如果要发送对象,则需要在发送端对其进行序列化,并在接收端对其进行反序列化。有大量的序列化方法,例如 JSON、XML,甚至 Java 的内置序列化支持(仅在客户端和服务器始终为 Java 时才推荐)。

        【讨论】:

          【解决方案5】:

          您可能会发现此代码是创建自己的课程的一个不错的起点。这是我创建的两个类,在某种程度上抽象了 TCP 和 UDP 套接字协议所需的工作:

          http://code.google.com/p/hivewars/source/browse/trunk/SocketData.java http://code.google.com/p/hivewars/source/browse/trunk/UDPSocket.java

          快速免责声明:这些是功能完整类的一种版本,我只是根据需要添加了功能。但是,它可以帮助您开始。

          【讨论】:

            猜你喜欢
            • 2018-06-10
            • 1970-01-01
            • 2013-11-11
            • 1970-01-01
            • 1970-01-01
            • 2023-04-05
            • 1970-01-01
            • 2011-11-15
            • 1970-01-01
            相关资源
            最近更新 更多