【Java】GUI界面聊天小程序(基於Socket的客戶端服務端通信)

基於Socket的客戶端服務端通信--Java GUI界面小程序

Socket概念及其通信過程:

Socket是TCP/IP中的基本概念,它負責將TCP/IP包發送到指定的IP地址。也可以看成是在兩個程序進行通信連接中的一個端點,一個程序將 信息寫入Socket中(類似於插座),該Socket將這段信息發送到另一個Socket中(類似於插頭),使這段信息能夠傳送到其他程序。這兩端的程序可以是在一臺計算機 上,也可以在因特網的遠程計算機上。

當兩個程序需要通信時,可以使用Socket類建立套接字連接。呼叫的一方稱爲客戶機,負責監聽的一方稱爲服務器。 由於TCP/IP協議是基於連接的、可靠的協議,所以客戶機服務器可以在這條連接上可靠地傳輸數據。服務器所用的套接字是ServerSocket, 客戶機所用的套接字是Socket。一個Socket由一個IP地址和一 個端口號唯一確定 。
在傳統的UNIX環境下可以操作TCP/IP協議的接口不止Socket一個,Socket 所支持的協議種類也不光TCP/IP -種,因此兩者之間是沒有必然聯繫的。在Java環境下,Socket編程主要是指基於TCP/IP協議的網絡編程。
使用Socket 進行Client/Server程序設計的一般連接過程 是這樣的: Server 端Listen (監聽)某個端口是否有連接請求,Client 端向Server端發出Connect (連接)請求,Server 端向Client端發回Accept (接收)消息。-個連接就建 立起來了。Server 端和Client端都可以通過Send和Write等方法與對方通信。
對於一個功能齊全的Socket,其工作過程包含以下4個基本的步驟。

  1. 創建Socket
  2. 打開連接到Socket的輸入/輸出流。
  3. 按照一定的協議對Socket進行讀寫操作。
  4. 關閉Socket。

當用戶輸入一行文字時,程序將接受數據部分放在線程中,它始終在後臺運行,一旦對方發來數據,就立即顯示在界面上。而主界面負責輸入文字和發送數據,這樣發送和接受數據互不影響。

服務端代碼:

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

public class ChatServer implements ActionListener, Runnable {

    JTextArea showArea;
    JTextField msgText;
    JFrame mainJframe;
    JButton sentBtn;
    JScrollPane JSPane;
    JPanel pane;
    Container con;
    Thread thread = null;
    ServerSocket serverSocket;
    Socket connectToClient;
    DataInputStream inFromClient;
    DataOutputStream outToClient;

    public ChatServer() {
        //設置界面
        mainJframe = new JFrame("聊天——服務端");
        con = mainJframe.getContentPane();
        showArea = new JTextArea();
        showArea.setEditable(false);
        showArea.setLineWrap(true);
        JSPane = new JScrollPane(showArea);
        msgText = new JTextField();
        msgText.setColumns(30);
        msgText.addActionListener(this);
        sentBtn = new JButton("發送");
        sentBtn.addActionListener(this);
        pane = new JPanel();
        pane.setLayout(new FlowLayout());
        pane.add(msgText);
        pane.add(sentBtn);
        con.add(JSPane, BorderLayout.CENTER);
        con.add(pane, BorderLayout.SOUTH);
        mainJframe.setSize(500, 400);
        mainJframe.setVisible(true);
        mainJframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ;
        try {
            //創建服務套接字
            serverSocket = new ServerSocket(5500);
            showArea.append("正在等待對話請求...\n");//偵聽客戶端的連接
            connectToClient = serverSocket.accept();
            inFromClient = new DataInputStream(connectToClient.getInputStream());
            outToClient = new DataOutputStream(connectToClient.getOutputStream());
            //啓動線程在後臺來接收對方的消息
            thread = new Thread(this);
            thread.setPriority(Thread.MIN_PRIORITY);
            thread.start();
        } catch (IOException e) {
            showArea.append("對不起,不能創建服務器\n");
            msgText.setEditable(false);
            sentBtn.setEnabled(false);
        }
    }

    public static void main(String[] args){
        new ChatServer();
    }

    @Override
    //響應按鈕事件,發送消息給對方
    public void actionPerformed(ActionEvent e) {
        String s = msgText.getText();
        if (s.length() > 0) {
            try {
                outToClient.writeUTF(s);
                outToClient.flush();
                showArea.append("我(服務端)說:" + msgText.getText() + "\n");
                msgText.setText(null);
            } catch (IOException el) {
                showArea.append("你的消息:“" + msgText.getText() + "”未能發出去!\n");
            }
        }
    }

    @Override
    //本線程負責將客戶機傳來的信息顯示在對話區域
    public void run() {
        try{
            while (true){
                showArea.append("客戶端說:"+inFromClient.readUTF()+"\n");
                Thread.sleep(1000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

客戶端代碼:

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

public class ChatClient implements ActionListener,Runnable{
    JTextArea showArea;
    JTextField msgText;
    JFrame mainJframe;
    JButton sentBtn;
    JScrollPane JSPane;
    JPanel pane;
    Container con;
    Thread thread=null;
    Socket connectToServer;
    DataInputStream inFromServer;
    DataOutputStream outToServer;

    public ChatClient(){
        mainJframe=new JFrame("聊天——客戶端");
        con=mainJframe.getContentPane();
        showArea=new JTextArea();
        showArea.setEditable(false);
        showArea.setLineWrap(true);
        JSPane=new JScrollPane(showArea);
        msgText=new JTextField();
        msgText.setColumns(30);
        msgText.addActionListener(this);
        sentBtn=new JButton("發送");
        sentBtn.addActionListener(this);

        pane=new JPanel();
        pane.setLayout(new FlowLayout());
        pane.add(msgText);
        pane.add(sentBtn);

        con.add(JSPane, BorderLayout.CENTER);
        con.add(pane, BorderLayout.SOUTH);
        mainJframe.setSize (500 ,400);
        mainJframe.setVisible (true);
        mainJframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //創建套接字連接到服務器
        try{
            connectToServer=new Socket("localhost",5500);
            inFromServer=new DataInputStream(connectToServer.getInputStream());
            outToServer=new DataOutputStream(connectToServer .getOutputStream());
            showArea.append("連接成功,請說話...\n");

            //創建線程在後臺處理對方的消息
            thread=new Thread(this);
            thread.setPriority(Thread.MIN_PRIORITY);
            thread.start();
        } catch (UnknownHostException e1){
            e1.printStackTrace();
        } catch (IOException e1){
            showArea.append("抱歉,未能連接到服務器!\n");
            msgText.setEditable(false);
            sentBtn.setEnabled(false);
        }
    }

    public static void main(String[] args){
        new ChatClient();
    }


    @Override
    //
    public void actionPerformed(ActionEvent e){
        String s=msgText.getText();
        if (s.length()>0){
            try{
                outToServer.writeUTF(s);
                outToServer.flush();
                showArea.append("我(客戶端)說: "+msgText. getText()+"\n");
            } catch (IOException e1){
                showArea.append("你的消息:“"+msgText.getText()+"”未能發送出去!\n");
            }
        }

    }

    //本線程負責將服務器傳來的消息顯示在對話區域
    public void run(){
        try{
            while (true){
                showArea.append("服務端說:"+inFromServer.readUTF()+"\n");
                Thread.sleep(1000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}

編譯後首先運行服務端,在運行客戶端。截圖如下:

在這裏插入圖片描述

在這裏插入圖片描述


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