記一次java socket學習(簡單實用多執行緒,實現多對多群聊)
阿新 • • 發佈:2019-01-03
學習過程是艱苦,學習結束是快樂的
目錄
用 [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。。。哎,期望下一次回頭看這個部落格,能有很大的提高。