Socket 客戶端-服務器(C-S)通信實驗

           學習計算機網絡編程也有一段時間了,對這段時間學習的東西做一個小總結吧,主要是基於socket,實現客戶端和服務器的通信,編程用java語言。具體的實驗要求如下:

設計程序,分別構建通信的兩端:服務器端和客戶端應用程序,套接字類型爲面向連接的Socket,自己構建雙方的應答模式,實現雙方的數據的發送和接收(S發給C,C發給S)。

服務端程序能響應單個或任意多個客戶端連接請求;服務端能向單個客戶發送消息,支持羣發消息給所有客戶端;
通信的雙方具備異常響應功能,包括對方異常退出的處理。如果客戶端退出,服務器有響應;反之亦然。
Client-Server通信效果的圖片說明:


       編程實現的思路:在服務器端,首先要啓動一條線程用於監聽某個指定端口(比如:8000),並且還要再開一條線程用於接收消息,客戶端嘗試連接該端口(8000),如果成功連接則會返回一個Socket類的實例對象(Socket socket = serversocket.accept();) ,很顯然服務器端便應該保存有一個客戶列表(比如可以用:ArrayList),使得服務器可以發消息給某個指定的客戶端。而客戶端在連接服務器之後也應該啓動一條線程用於接收消息。當某個客戶端進來時,便發送Login消息給服務器,服務器將此消息廣播發給當前在線的所有用戶,當某個客戶端退出時,發送Logout消息給服務器,服務器將此消息廣播發給當前在線的所有用戶,當客戶端之間進行通信時,會發送Talk消息給服務器,服務器再將此消息轉發給指定的客戶端,也就是所有的通信都是通過服務器進行轉發的。

主要的代碼實現如下:

   服務器端:

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.swing.JScrollBar;


public class ChatServer extends javax.swing.JFrame {
    ArrayList<User> list = new ArrayList<User>();
    static String local;
    int port = 8000;
    boolean isNomalexit = false;
    Mythread  jtThread;


    public ChatServer() {
        initComponents();
        this.setTitle("服務器");
        this.setResizable(false);
        this.setLocationRelativeTo(null);
         this.addWindowListener(new WindowAdapter() {  
                   public void windowClosing(WindowEvent e) {                            
                       super.windowClosing(e);
                       dispose();
                            
                   }
                });
    }

 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)  { } //開始監聽按鈕的事件

 private void jButton2ActionPerformed(java.awt.event.ActionEvent evt)  { } //停止監聽按鈕的事件

class Mythread extends Thread{ }                //負責監聽端口8000的線程

class ClientThread extends Thread{ }          //負責接收消息的線程

public void sendtoclient(User user,String message){ }     //發送消息message給用戶,user爲發送者

public void sendtoallclient(User user,String message){ }  //發送消息message給所有用戶,user發送者

public void removeuser(User user){ }

 public static void main(String args[]) throws UnknownHostException {
             local = InetAddress.getLocalHost().getHostAddress();
             ChatServer frame = new ChatServer();
             frame.setVisible(true);
    
    }


  客戶端:

import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JScrollBar;

public class ChatClient extends javax.swing.JFrame {
       Socket s;
       boolean isExit = false;
       DataInputStream in;
       PrintStream out;
       ArrayList<String> list =new  ArrayList<String>();
       static String name;
       ReceivemessageThread thread;

    public ChatClient() {
        initComponents();
        this.setTitle("客戶端");
        this.setResizable(false);
        this.setLocationRelativeTo(null);
         this.addWindowListener(new WindowAdapter() {  
                   public void windowClosing(WindowEvent e) {       
                      if(s!=null){
                          sendmessage("Logout " + name);
                          try {
                              isExit = true;
                              in.close();
                               out.close();
                               s.close();
                          } catch (IOException ex) {
                              Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
                          }                    
                       }         
                   }
              });
    }           

 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){ } //登錄按鈕的事件

 private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){ } //發送按鈕的事件  

 class ReceivemessageThread extends Thread{ } // 接收消息的線程

 public void sendmessage(String message){ }  //發送消息

public void removeuser(String name){ } //移除在線列表上的用戶名

 public static void main(String args[]) {
            ChatClient frame = new ChatClient();
            frame.setVisible(true);
    }


運行演示:





在做完這個程序之後,對於網絡編程也算是基本上入門了,後續還會有很多的通信程序,因爲這門課的要求就是做一個類似QQ的通信程序,寫下這篇博客也算是記錄自己的學習進程。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章