簡體   English   中英

服務器和客戶端使用套接字

[英]Server and Client using Sockets

是否有使用套接字但具有send和get方法的服務器和客戶端的任何示例? 我正在做這個聯網的戰列艦程序,快要完成了,但是無法使服務器和客戶端正常工作。 我制作了一個僅發送字符串的聊天程序,但是這次我需要發送對象。 我已經很沮喪,所以是否有任何源代碼已經有了這個。

這是客戶端的代碼...您將如何對其進行修改以允許發送對象? 另外,我還需要監聽傳入的對象並立即對其進行處理。

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

我建議您閱讀Java序列化。 有一個例子在這里 基本上,內置了序列化支持。 您的課程需要實現Serializable 然后,使用ObjectOutputStreamObjectInputStream編寫對象。

強烈建議您使用使您免於容易出錯的低級套接字編程的庫。

對於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,但是我確定某個地方有實現

您走對了。 聊天程序是開始學習套接字的好地方。

您要使用ObjectOutputStream和ObjectInputStream類。 您只需要用這些過濾器包裝您的輸入流/輸出流。 ObjectOutputStream具有方法writeObject(),而ObjectInputStream具有對應的readObject()方法。

大多數序列化示例都顯示了將對象讀取和寫入文件的過程,但是可以使用套接字流來完成相同的操作。 參見http://www.acm.org/crossroads/xrds4-2/serial.html

我不花時間閱讀大量的代碼,但是總的來說,您不能直接通過網絡發送對象。 網絡通信只是位和字節。 如果要發送對象,則需要在發送端對它們進行序列化,然后在接收端對它們進行反序列化。 有大量的序列化方法,例如JSON,XML甚至Java的內置序列化支持(僅當客戶端和服務器始終都是Java時才建議使用)。

您可能會發現此代碼是制作自己的類的一個不錯的起點。 我制作了兩個類,以稍微抽象化TCP和UDP套接字協議所需的工作:

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

快速免責聲明:這些是全功能類的一種版本,我只是在需要時添加了功能。 但是,它可以幫助您開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM