1. 程式人生 > >記一次java socket學習(簡單實用多執行緒,實現多對多群聊)

記一次java socket學習(簡單實用多執行緒,實現多對多群聊)

學習過程是艱苦,學習結束是快樂的

目錄

[TOC]來生成目錄:

本來想寫一些文字描述描述,可是想不出來說啥。。。所以直接記錄程式碼了。。。

程式碼塊

因為喜歡把常量都提取出來 所以上來就是常量類:

public class Constant {
    //這個埠要提示一下,有的時候你佔用系統的埠,所以當啟動服務端的時候,直接就有客戶端連結
    public static final int PORT_NUM =8887;
    public static final String LOCALHOST="localhost";
}

服務端:


package com.gs.socket2;

import
java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import static com.gs.constant.Constant.PORT_NUM; /** * Created with GaoShan. * Description: * Date: 2017-07-24 * Time: 8:29 */ public class Server
{ public static void main(String[] args) { new Server().service(); } void service(){ //宣告服務端socket ServerSocket serverSocket =null; //宣告連結到伺服器的客戶端 Socket client =null; //宣告客戶端集合,用於群發 List<Socket> clients = new ArrayList<>()
; try { serverSocket = new ServerSocket(PORT_NUM); System.out.println("伺服器啟動,等待客戶端連結!"); int count = 0; while (true){ client = serverSocket.accept(); clients.add(client); InetAddress inetAddress = client.getInetAddress(); System.out.println("客戶端:"+inetAddress.getHostName()+"連結伺服器,當前連線數:" +clients.size()); ServerThread serverThread = new ServerThread(client, clients); serverThread.setName("客戶端"+count++); serverThread.start(); } } catch (IOException e) { e.printStackTrace(); clients.remove(client); } } }

伺服器的執行緒類:


package com.gs.socket2;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import static com.gs.constant.Constant.PORT_NUM;

/**
 * Created with GaoShan.
 * Description:
 * Date: 2017-07-24
 * Time: 8:29
 */
package com.gs.socket2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;

/**
 * Created with GaoShan.
 * Description:
 * Date: 2017-07-24
 * Time: 8:29
 */
public class ServerThread extends Thread {
    private Socket client;
    private List<Socket> clients;
    private BufferedReader bufferedReader;
    private PrintWriter printWriter;

    public ServerThread(Socket client, List<Socket> clients) {
        this.client = client;
        this.clients = clients;
    }

    @Override
    public void run() {
        super.run();
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
            while (true) {
                String readLine = bufferedReader.readLine();
                System.out.println("來自客戶端的訊息:" + readLine);
                if (readLine.equals("exit"))
                    break;
                for (Socket socket:clients){
                    //不給客戶端本身轉發訊息
                    if(client.equals(socket))
                        continue;
                    printWriter = new PrintWriter(socket.getOutputStream());
                    printWriter.println(getName()+"發來訊息:" + readLine);
                    printWriter.flush();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            clients.remove(client);
            if (client != null) {
                try {
                    client.close();
                } catch (IOException a) {
                    a.printStackTrace();
                }
            }
        }
    }
}
寫伺服器執行緒的時候有個問題,就是不知道,應該在哪裡判斷客戶端是否斷開連結,或者,異常關閉了,也不知道怎麼處理。糾結,現在就想到一種就是不處理  e.printStackTrace(); 直接刪掉,但是感覺肯定不是這樣。

客戶端:

package com.gs.socket2;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import static com.gs.constant.Constant.LOCALHOST;
import static com.gs.constant.Constant.PORT_NUM;

/**
 * Created with GaoShan.
 * Description:
 * Date: 2017-07-24
 * Time: 8:29
 */
public class Client {

    public static void main(String args[]) {
        new Client().service();
    }

    void service() {
        //宣告連結到的伺服器
        Socket server = null;
        System.out.println("正在連結伺服器。。。");
        try {
            server = new Socket(LOCALHOST, PORT_NUM);
            InetAddress inetAddress = server.getInetAddress();
            System.out.println("成功連線:" + inetAddress.getHostName() + ",ip地址為:" + inetAddress.getHostAddress());
            new ClientThreadReceive(server).start();
            new ClientThreadSend(server).start();
        } catch (IOException e) {
            e.printStackTrace();
            if (server != null) {
                try {
                    server.close();
                } catch (IOException aaa) {
                    aaa.printStackTrace();
                }
            }
        }
    }
}

客戶端的接收執行緒:

package com.gs.socket2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * Created with GaoShan.
 * Description:
 * Date: 2017-07-24
 * Time: 8:29
 */
public class ClientThreadReceive extends Thread {
    private Socket server;

    public ClientThreadReceive(Socket server) {
        this.server = server;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(server.getInputStream()));
            while (true) {
                String readLine = br.readLine();
                System.out.println(readLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客戶端傳送執行緒:

package com.gs.socket2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * Created with GaoShan.
 * Description:
 * Date: 2017-07-21
 * Time: 13:39
 */
public class ClientThreadSend extends Thread {
    private Socket server;

    public ClientThreadSend(Socket server) {
        this.server = server;
    }

    @Override
    public void run() {
        super.run();

        try {
            PrintWriter printWriter = new PrintWriter(server.getOutputStream());
            BufferedReader clientBr = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                String readLine = clientBr.readLine();
                printWriter.println(readLine);
                printWriter.flush();
                if (readLine.equals("exit")) {
                    System.out.println("您斷開了與伺服器的連結!");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

本來寫個socket 挺簡單的,可是,優化來優化去,竟給自己挖了坑,比如咋finally用錯地方,直接導致,socket close。。。哎,期望下一次回頭看這個部落格,能有很大的提高。