計算機網絡原理 實驗2《Windows Socket編程》

實驗2《Windows Socket編程》

一、實驗目的

  通過實驗,使學生熟悉並掌握計算機Windows 編程的基本知識,進一步加深學生對課堂所學基本內容的理解,掌握基本的Windows編程技巧,通過實驗使得學生能夠進行一些簡單的網絡程序設計。

二、實驗內容
  1. 瞭解基本的Socket知識
  2. 基於java完成Socket編程,設計並實現一個簡單的聊天系統,包括客戶端及服務器端。
    2.1 完成服務端使用telnet與服務器通信
    2.2 完成客戶端與服務端通信
    2.3 完成基於多線程的實現服務端可以與多個客戶端通信
  3. 可選,重構現有代碼完成帶界面的軟件。實現各客戶端之間聊天,以及多人聊天室。
三、實驗方法

  實驗方法爲利用Intellij IDEA開發工具,JAVA編程語言實現,參考過往實驗資料與網絡資料之後自己實現完成。

四、實驗步驟
  1. 開啓本機的telnet服務,在終端輸入telnet可進行連接,輸入?可查看幫助信息。
    在這裏插入圖片描述
    在這裏插入圖片描述
  2. 打開Intellij IDEA開發工具進行項目程序編寫;
    2.1 實現了一個簡單的服務端: start函數負責建立服務端,等待連接,stop函數負責關閉連接以及相關的io流。Serversocket對象創建以後accept函數等待客戶端連接。若沒有客戶端連接上,則會一直輪詢,直到有客戶端連接上,繼續執行下面邏輯。當建立連接以後,雙方建立通信管道,io流讀取與寫入數據。完成socket通信。
//sampleServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class sampleServer {
    private ServerSocket serverSocket;
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader in;

    //建立服務端,等待連接
    public void start(int port) throws Exception{
        serverSocket = new ServerSocket(port);
        clientSocket = serverSocket.accept();
        out = new PrintWriter(clientSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null){
            if(".".equals(inputLine)){
                out.println("good bye");
                stop();
                break;
            }else{
                out.println("server got msg: "+inputLine);
            }
        }
    }

    //關閉連接以及相關的io流
    public void stop() throws Exception{
        in.close();
        out.close();
        clientSocket.close();
        serverSocket.close();
    }

    public static void main(String[] args){
        try {
            sampleServer server = new sampleServer();
            server.start(23);
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

  此時,可以使用telnet連接,輸入信息,即可發送給服務端。服務端接收到處理後返回。
在這裏插入圖片描述
在這裏插入圖片描述

  2.2 完成客戶端與服務端通信
  在完成了可以使用telnet連接,並與之通信的服務器以後,我們編寫自己的客戶端代碼與服務器進行通信。代碼很簡單。
  StartConnection函數指定ip與端口,若與服務器成功建立連接,則獲取建立的通道的io流,out與in輸入輸出流,來實現後續與服務端的消息接收與發送。
  sendMessage函數基於io流發送消息。
  StopConnection關閉與服務端的連接。
  主函數獲得用戶在命令行的輸入,發送給服務端。

//sampleClient.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class sampleClient {
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader in;

    //指定ip和端口
    public void startConnection(String ip, int port)throws Exception{
        clientSocket = new Socket(ip, port);
        out = new PrintWriter(clientSocket.getOutputStream(),true);
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    }

    //基於IO流發消息
    public String sendMessage(String msg)throws Exception{
        out.println(msg);
        String resp = in.readLine();
        return resp;
    }

    //關閉與服務端的連接
    public void stopConnection(){
        try {
            in.close();
            out.close();
            clientSocket.close();
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    public static void main(String[] args){
        try{
            //bulid the connection
            sampleClient client = new sampleClient();
            client.startConnection("127.0.0.1",23);
            //recevice the input string from termnal and send it to server
            Scanner sc = new Scanner((System.in));
            while (true){
                String response = client.sendMessage(sc.nextLine());
                System.out.println(response);
                if(response.equals("good bye")){
                    client.stopConnection();
                    break;
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

  2.3 完成基於多線程的實現服務端可以與多個客戶端通信
  完成以上實驗,即可使用socket實現客戶端與服務端之間的交互,進行簡單的消息發送與接收。接下來我們可以實現多線程技術。
  將上面服務器代碼的獲取io流,收發消息代碼移植到clientHandler類中,該類繼承自thread類。
  修改start函數,依然是在本地的一個端口進行監聽,但是我們這裏使用一個循環來將每一個連接上來的client交給clientHandler來進行處理,這樣主進程就不會阻塞,可以繼續接收新客戶端的連接,從而實現一個服務端連接多個客戶端並與之通信的功能。
  同時需要注意,我們使用一個clientList來維護所有的客戶端。代碼如下所示:

//clientList.java
import java.util.ArrayList;

public class clientList {
    public static ArrayList clientList;

    static {
        clientList = new ArrayList<multiServer.clientHandler>();
    }
}
//multiServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class multiServer {
    private ServerSocket serverSocket;

    public void start(int port)throws Exception{
        serverSocket = new ServerSocket(port);
        while (true){
            clientHandler client = new clientHandler(serverSocket.accept());
            clientList.clientList.add(client);
            client.start();
        }
    }

    public void stop() throws Exception{
        serverSocket.close();
    }

    public static class clientHandler extends Thread{
        private Socket clientSocket;
        private PrintWriter out;
        private BufferedReader in;

        public clientHandler(Socket socket){
            this.clientSocket = socket;
        }

        public void run(){
            try{
                out = new PrintWriter(clientSocket.getOutputStream(),true);
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                String inputLine;
                while ((inputLine = in.readLine()) != null){
                    if(".".equals(inputLine)){
                        out.println("good bye");
                        break;
                    }
                    out.println("msg from client" + clientList.clientList.indexOf(this) + "--msg:" + inputLine);
                }
                in.close();
                out.close();
                clientSocket.close();
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}
//main.java
public class main {
    public static void main(String[] args){
        try{
            new multiServer().start(23);
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
五、實驗結果

  實驗運行步驟及結果如下所示:

  1. 在Intellij IDEA中運行main函數;
  2. 運行命令行,輸入telnet,連接telnet服務,再輸入o,輸入連接主機 localhost;
    在這裏插入圖片描述
  3. 接下來便可以運行第一個客戶端,客戶端即可輸入信息,服務端可以反饋;
    在這裏插入圖片描述
  4. 重複第二步第三步即可開啓多個客戶端;
    在這裏插入圖片描述
    在這裏插入圖片描述
六、實驗小結

  本次實驗是要是瞭解socket編程知識,客戶端與服務端的交互,多閱讀相關資料熟悉實驗中需使用的方法就會輕鬆很多。

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