Java SE實(shí)現(xiàn)多人聊天室功能
本文實(shí)例為大家分享了Java SE實(shí)現(xiàn)多人聊天室功能的具體代碼,供大家參考,具體內(nèi)容如下
實(shí)現(xiàn)功能:
1.實(shí)現(xiàn)用戶注冊(cè)上線,下線
2.實(shí)現(xiàn)群聊和私聊功能
3.實(shí)現(xiàn)統(tǒng)計(jì)當(dāng)前在線人數(shù)
實(shí)現(xiàn)思路:
1.首先,要實(shí)現(xiàn)服務(wù)端與客戶端之間的連接
這里是使用套接字建立TCP連接:
(1)服務(wù)器端先實(shí)例化一個(gè)描述服務(wù)器端口號(hào)的ServerSocket對(duì)象
(2)客戶端要?jiǎng)?chuàng)建Socket對(duì)象來(lái)連接指定的服務(wù)器端
(3)服務(wù)器端調(diào)用ServerSocket類的accept()方法來(lái)監(jiān)聽(tīng)連接到服務(wù)器端的客戶端信息
(4)若服務(wù)器端與客戶端連接成功,雙方將返回一個(gè)Socket對(duì)象,此時(shí)雙方可以進(jìn)行通信
(5)服務(wù)器端與客戶端使用I/O流進(jìn)行連接,服務(wù)端的輸出流連接客戶端的輸入流,客戶端的輸出流連接服務(wù)端的輸入流
(6)使用close()方法關(guān)閉套接字(一定要記得關(guān)閉)
2.因?yàn)槭菗碛幸粋€(gè)服務(wù)端來(lái)實(shí)現(xiàn)多個(gè)客戶端的連接,此處還要解決的是多線程的問(wèn)題。
每個(gè)客戶端需要兩個(gè)線程,來(lái)分別處理向服務(wù)端發(fā)送消息和向服務(wù)端接收消息
而服務(wù)端,當(dāng)每增加一個(gè)客戶端與服務(wù)端連接,服務(wù)端都要多創(chuàng)建一個(gè)線程來(lái)處理與客戶端的連接
具體代碼:
單線程實(shí)現(xiàn):
客戶端
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* @author LXY
* @email 403824215@qq.com
* @date 2018/7/20 15:46
*/
//客戶端
public class SingleClient {
public static void main(String[] args) throws IOException {
//客戶端連接服務(wù)器,返回套接字Socket對(duì)象
Socket socket = new Socket("127.0.0.1",6666);
//獲取服務(wù)端的輸出流,向服務(wù)器端輸出內(nèi)容
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("我是客戶端" + socket.getLocalPort());
//獲取服務(wù)器端的輸入流,讀取服務(wù)器端的內(nèi)容
Scanner scanner = new Scanner(socket.getInputStream());
scanner.useDelimiter("\n");
if(scanner.hasNext())
{
System.out.println(scanner.next());
}
//關(guān)閉流
socket.close();
}
}
服務(wù)端
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @author LXY
* @email 403824215@qq.com
* @date 2018/7/20 15:34
*/
//服務(wù)端
public class SingleServer {
public static void main(String[] args) throws IOException {
//創(chuàng)建服務(wù)器端的ServerSocket對(duì)象,等待客戶端進(jìn)行連接
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服務(wù)器的端口號(hào)為6666,等待客戶端連接。。。");
//偵聽(tīng)并接收服務(wù)器端的連接,返回套接字Socket對(duì)象
Socket socket = serverSocket.accept();
//獲取客戶端的輸入流,讀取客戶端的輸入內(nèi)容
Scanner scanner = new Scanner(socket.getInputStream());
scanner.useDelimiter("\n");
if(scanner.hasNext())
{
System.out.println("客戶端發(fā)來(lái)消息:" + scanner.next());
}
//獲取客戶端的輸出流,向客戶端輸出內(nèi)容
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("客戶端你好,我是服務(wù)器端:" + serverSocket.getLocalPort());
//關(guān)閉流
serverSocket.close();
}
}
多線程實(shí)現(xiàn)
客戶端
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* @author LXY
* @email 403824215@qq.com
* @date 2018/7/20 15:55
*/
//客戶端
//客戶端讀取服務(wù)器端信息的線程
class ClientReadServer implements Runnable
{
private Socket socket;
public ClientReadServer(Socket socket)
{
this.socket = socket;
}
public void run() {
try {
Scanner scanner = new Scanner(socket.getInputStream());
while (scanner.hasNext())
{
System.out.println(scanner.next());
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//客戶端向服務(wù)端發(fā)送信息的線程
class ClientSendServer implements Runnable
{
private Socket socket;
public ClientSendServer(Socket socket)
{
this.socket = socket;
}
public void run() {
try {
PrintStream printStream = new PrintStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while (true)
{
String msg = null;
if(scanner.hasNext())
{
msg = scanner.next();
printStream.println(msg);
}
if(msg.equals("bye"))
{
scanner.close();
printStream.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MultiClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",6666);
Thread read = new Thread(new ClientReadServer(socket));
Thread send = new Thread(new ClientSendServer(socket));
read.start();
send.start();
}
}
服務(wù)端
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author LXY
* @email 403824215@qq.com
* @date 2018/7/20 16:12
*/
class Server implements Runnable
{
private static Map<String,Socket> map = new ConcurrentHashMap<String, Socket>();
private Socket socket;
public Server(Socket socket)
{
this.socket = socket;
}
public void run() {
try {
Scanner scanner = new Scanner(socket.getInputStream());
String msg = null;
while (true)
{
if(scanner.hasNextLine())
{
msg = scanner.nextLine();
Pattern pattern = Pattern.compile("\r");
Matcher matcher = pattern.matcher(msg);
msg = matcher.replaceAll("");
//用戶注冊(cè)——格式:userName:用戶名
if(msg.startsWith("userName:"))
{
String userName = msg.split("\\:")[1];
userRegist(userName,socket);
continue;
}
//群聊——格式:G:群聊信息
else if(msg.startsWith("G:"))
{
firstStep(socket);
String str = msg.split("\\:")[1];
groupChat(socket,str);
continue;
}
else if(msg.startsWith("P:") && msg.contains("-"))
{
firstStep(socket);
String userName = msg.split("\\:")[1].split("-")[0];
String str = msg.split("\\:")[1].split("-")[1];
privateChat(socket,userName,str);
continue;
}
else if(msg.contains("bye"))
{
firstStep(socket);
userExit(socket);
continue;
}
else
{
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("格式輸入錯(cuò)誤");
continue;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void firstStep(Socket socket) throws IOException {
Set<Map.Entry<String,Socket>> set = map.entrySet();
for(Map.Entry<String,Socket> entry:set)
{
if(entry.getValue().equals(socket))
{
if(entry.getValue() == null)
{
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("請(qǐng)先進(jìn)行注冊(cè)操作!格式為:[userName:用戶名]");
}
}
}
}
private void userRegist(String userName, Socket socket) {
map.put(userName,socket);
System.out.println("用戶名:" + userName + "客戶端" + socket +"上線了??!");
System.out.println("當(dāng)前在線人數(shù)為" + map.size() + "人");
}
private void groupChat(Socket socket, String msg) throws IOException {
Set<Map.Entry<String,Socket>> set = map.entrySet();
String userName = null;
for(Map.Entry<String,Socket> entry:set)
{
if(entry.getValue().equals(socket))
{
userName = entry.getKey();
break;
}
}
for(Map.Entry<String,Socket> entry:set)
{
Socket client = entry.getValue();
PrintStream printStream = new PrintStream(client.getOutputStream());
printStream.println(userName + "說(shuō)" + msg);
}
}
private void privateChat(Socket socket, String userName, String msg) throws IOException {
String curUser = null;
Set<Map.Entry<String,Socket>> set = map.entrySet();
for(Map.Entry<String,Socket> entry:set)
{
if(entry.getValue().equals(socket))
{
curUser = entry.getKey();
break;
}
}
Socket client = map.get(userName);
PrintStream printStream = new PrintStream(client.getOutputStream());
printStream.println(curUser + "私聊說(shuō)" + msg);
}
private void userExit(Socket socket) {
String userName = null;
for(String key:map.keySet())
{
if(map.get(key).equals(socket))
{
userName = key;
break;
}
}
map.remove(userName,socket);
System.out.println("用戶" + userName + "已下線");
}
}
public class MultiServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(6666);
//使用線程池
ExecutorService executorService = Executors.newFixedThreadPool(20);
for(int i = 0;i < 20;i++)
{
System.out.println("歡迎來(lái)到聊天室。。。");
Socket socket = serverSocket.accept();
System.out.println("新人加入。。。");
executorService.execute(new Server(socket));
}
executorService.shutdown();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- java socket實(shí)現(xiàn)聊天室 java實(shí)現(xiàn)多人聊天功能
- 基于java編寫(xiě)局域網(wǎng)多人聊天室
- java編程實(shí)現(xiàn)多人聊天室功能
- Java基于Tcp/ip連接的多人交互聊天室
- java使用MulticastSocket實(shí)現(xiàn)基于廣播的多人聊天室
- Java NIO Selector用法詳解【含多人聊天室實(shí)例】
- java實(shí)現(xiàn)多人聊天工具(socket+多線程)
- Java多線程實(shí)現(xiàn)多人聊天室功能
- Java基于中介者模式實(shí)現(xiàn)多人聊天室功能示例
- java實(shí)現(xiàn)多人聊天系統(tǒng)
相關(guān)文章
java 中動(dòng)態(tài)代理(JDK,cglib)實(shí)例代碼
這篇文章主要介紹了java 中動(dòng)態(tài)代理,這里介紹了JDK 動(dòng)態(tài)代理與 cglib 動(dòng)態(tài)代理的相關(guān)資料2017-04-04
簡(jiǎn)單理解Java的垃圾回收機(jī)制與finalize方法的作用
這篇文章主要介紹了簡(jiǎn)單理解Java的垃圾回收機(jī)制與finalize方法的作用,著重講解了Java的GC銷毀對(duì)象的過(guò)程,需要的朋友可以參考下2015-11-11
Java中的 VO,BO,DO 對(duì)象命名問(wèn)題小結(jié)
本文講解VO,BO,DO 的作用以及如何使用,分析了如何消除三者之間重復(fù)的代碼,同樣結(jié)合現(xiàn)實(shí)生活中領(lǐng)導(dǎo)配秘書(shū)來(lái)類比講解,對(duì)Java VO 對(duì)象命名相關(guān)知識(shí)感興趣的朋友一起看看吧2024-01-01
IntelliJ IDEA設(shè)置JVM運(yùn)行參數(shù)的操作方法
這篇文章主要介紹了IntelliJ IDEA設(shè)置JVM運(yùn)行參數(shù)的操作方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-03-03
Java實(shí)現(xiàn)每日給女友微信發(fā)送早安信息
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)每日給女友微信發(fā)送早安等微信信息,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以了解一下2022-12-12
mybatis Example Criteria like 模糊查詢問(wèn)題
這篇文章主要介紹了mybatis Example Criteria like 模糊查詢問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02

