简体   繁体   English

服务器和客户端使用套接字

[英]Server and Client using Sockets

Are there any examples of a server and a client that use sockets, but that have send and get methods? 是否有使用套接字但具有send和get方法的服务器和客户端的任何示例? I'm doing this networked battleship program, almost finished, but can't get the server and clients to work. 我正在做这个联网的战列舰程序,快要完成了,但是无法使服务器和客户端正常工作。 I have made a chat program that only sends strings, but this time I need to send objects. 我制作了一个仅发送字符串的聊天程序,但是这次我需要发送对象。 I'm already frustrated, so is there any source code that already has this. 我已经很沮丧,所以是否有任何源代码已经有了这个。

Here's the code for the client... how would you modify it to allow to send objects? 这是客户端的代码...您将如何对其进行修改以允许发送对象? Also I need to be listening for incoming objects and process them right away. 另外,我还需要监听传入的对象并立即对其进行处理。

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();
  }
}

I suggest you read up on java serialization. 我建议您阅读Java序列化。 There is an example here . 有一个例子在这里 Basically, there is built in serialization support. 基本上,内置了序列化支持。 Your class needs to implement Serializable . 您的课程需要实现Serializable Then you use ObjectOutputStream and ObjectInputStream to write object. 然后,使用ObjectOutputStreamObjectInputStream编写对象。

You would be well advised to use libraries that shield you from the error prone low level socket programming. 强烈建议您使用使您免于容易出错的低级套接字编程的库。

For C++ look to Boost ( http://www.boost.com ) or ACE ( http://www.cs.wustl.edu/~schmidt/ACE.html ) 对于C ++,请看Boost( http://www.boost.com )或ACE( http://www.cs.wustl.edu/~schmidt/ACE.html

For Java I only found a document that talks about the acceptor pattern http://www.hillside.net/plop/plop99/proceedings/Fernandez3/RACPattern.PDF But I am sure there's an implementation out somewhere 对于Java,我只找到了一个有关接受者模式的文档, 网址为http://www.hillside.net/plop/plop99/proceedings/Fernandez3/RACPattern.PDF,但是我确定某个地方有实现

Your on the right track. 您走对了。 A chat program is a good place to start learning about sockets. 聊天程序是开始学习套接字的好地方。

What you want is to use the ObjectOutputStream and ObjectInputStream classes. 您要使用ObjectOutputStream和ObjectInputStream类。 You simply have to wrap your input stream / output stream with these filters. 您只需要用这些过滤器包装您的输入流/输出流。 ObjectOutputStream has a method writeObject(), and the ObjectInputStream has a corresponding readObject() method. ObjectOutputStream具有方法writeObject(),而ObjectInputStream具有对应的readObject()方法。

Most serialization examples show reading and writing objects to a file, but the same can be done using a socket stream. 大多数序列化示例都显示了将对象读取和写入文件的过程,但是可以使用套接字流来完成相同的操作。 See http://www.acm.org/crossroads/xrds4-2/serial.html 参见http://www.acm.org/crossroads/xrds4-2/serial.html

I didn't bother to read through your piles and piles of code, but in general you can't directly send objects over the network. 我不花时间阅读大量的代码,但是总的来说,您不能直接通过网络发送对象。 Network communication is just bits and bytes. 网络通信只是位和字节。 If you want to send objects, you'll need to serialize them on the sending side, and de-serialize them on the receiving side. 如果要发送对象,则需要在发送端对它们进行序列化,然后在接收端对它们进行反序列化。 There are tons of methods of serializing, eg JSON, XML, or even Java's built-in serialization support (only recommended if both the client and server will always be Java). 有大量的序列化方法,例如JSON,XML甚至Java的内置序列化支持(仅当客户端和服务器始终都是Java时才建议使用)。

You may find this code to be a decent starting point for making your own class. 您可能会发现此代码是制作自己的类的一个不错的起点。 These are two classes I made to somewhat abstract the work needed for TCP and UDP socket protocols: 我制作了两个类,以稍微抽象化TCP和UDP套接字协议所需的工作:

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

Quick dislaimer: These are kind of versions of a feature full class, I just added functionality as I needed it. 快速免责声明:这些是全功能类的一种版本,我只是在需要时添加了功能。 However, it could help you start. 但是,它可以帮助您开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM