本篇文章和大家一起分享Java基于Socket來實現(xiàn)多人聊天室的具體代碼,詳細內(nèi)容如下:
Socket可以實現(xiàn)網(wǎng)絡(luò)上兩個程序通過雙向通道進行數(shù)據(jù)的交換,此外它是Java中網(wǎng)絡(luò)TCP/IP協(xié)議的封裝,例如可以進行網(wǎng)絡(luò)通信等等,下面我們就來簡單寫一下多人聊天室。
首先來分析一下要實現(xiàn)的流程
- 首先建立一個服務(wù)器端,構(gòu)建ServerSocket并綁定端口
- 創(chuàng)建socket客戶端,連接到指定ip以及其端口
- 然后使用accept阻塞接收socket發(fā)出的連接請求
- 獲取連接后的socket客戶端的輸入流和輸出流
- 根據(jù)輸入流和輸出流進行兩者數(shù)據(jù)的通信
值得一提是:該Socket是同步阻塞的,因此在socket客戶端需要進行創(chuàng)建一個線程,來分別進行向服務(wù)器輸出,和接收服務(wù)器傳輸?shù)臄?shù)據(jù)。要解決同步阻塞這個問題可以去了解JAVA NIO。
Socket客戶端代碼如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client{
public static void main(String[] args) throws IOException {
//創(chuàng)建連接指定Ip和端口的socket
Socket socket = new Socket("127.0.0.1",5200);
//獲取系統(tǒng)標(biāo)準(zhǔn)輸入流
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//創(chuàng)建一個線程用于讀取服務(wù)器的信息
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true){
System.out.println(in.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//寫信息給客戶端
String line = reader.readLine();
while (!"end".equalsIgnoreCase(line)){
//將從鍵盤獲取的信息給到服務(wù)器
out.println(line);
out.flush();
//顯示輸入的信息
line = reader.readLine();
}
out.close();
in.close();
socket.close();
}
}
由于要接收多個客戶端的請求,因此服務(wù)端需要多個線程進行分別來接收客戶端的請求。
Socket服務(wù)端代碼如下:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.Vector;
public class Servers {
//將接收到的socket變成一個集合
protected static List<Socket> sockets = new Vector<>();
public static void main(String[] args) throws IOException {
//創(chuàng)建服務(wù)端
ServerSocket server = new ServerSocket(5200);
boolean flag = true;
//接受客戶端請求
while (flag){
try {
//阻塞等待客戶端的連接
Socket accept = server.accept();
synchronized (sockets){
sockets.add(accept);
}
//多個服務(wù)器線程進行對客戶端的響應(yīng)
Thread thread = new Thread(new ServerThead(accept));
thread.start();
//捕獲異常。
}catch (Exception e){
flag = false;
e.printStackTrace();
}
}
//關(guān)閉服務(wù)器
server.close();
}
}
Server線程代碼如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* 服務(wù)器線程,主要來處理多個客戶端的請求
*/
public class ServerThead extends Servers implements Runnable{
Socket socket;
String socketName;
public ServerThead(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//設(shè)置該客戶端的端點地址
socketName = socket.getRemoteSocketAddress().toString();
System.out.println("Client@"+socketName+"已加入聊天");
print("Client@"+socketName+"已加入聊天");
boolean flag = true;
while (flag)
{
//阻塞,等待該客戶端的輸出流
String line = reader.readLine();
//若客戶端退出,則退出連接。
if (line == null){
flag = false;
continue;
}
String msg = "Client@"+socketName+":"+line;
System.out.println(msg);
//向在線客戶端輸出信息
print(msg);
}
closeConnect();
} catch (IOException e) {
try {
closeConnect();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
/**
* 向所有在線客戶端socket轉(zhuǎn)發(fā)消息
* @param msg
* @throws IOException
*/
private void print(String msg) throws IOException {
PrintWriter out = null;
synchronized (sockets){
for (Socket sc : sockets){
out = new PrintWriter(sc.getOutputStream());
out.println(msg);
out.flush();
}
}
}
/**
* 關(guān)閉該socket的連接
* @throws IOException
*/
public void closeConnect() throws IOException {
System.out.println("Client@"+socketName+"已退出聊天");
print("Client@"+socketName+"已退出聊天");
//移除沒連接上的客戶端
synchronized (sockets){
sockets.remove(socket);
}
socket.close();
}
}
由于要接收多個客戶端的信息,并轉(zhuǎn)發(fā)到每一個已經(jīng)連接上的客戶端,因此創(chuàng)建了一個Vector集合來保存每一個客戶端Socket,由于是多個線程同時對這個Vector集合進行操作,因此加上synchronized關(guān)鍵字保證同步安全。
先運行服務(wù)器端,然后在運行多個客戶端就可以進行多人聊天了。
下面是運行的結(jié)果。
客戶端1
客戶端2
客戶端3
服務(wù)端
以上就是基于Socket多人聊天室,Java代碼實現(xiàn)的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。想要了解更多關(guān)于Java的內(nèi)容,請搜索W3Cschool以往的文章或者繼續(xù)瀏覽接下來的文章。