本文实例为大家分享了Java实现局域网聊天的具体代码,供大家参考,具体内容如下
开发环境:
IDEA 2018.2 集成开发工具。
实现功能:
1、用户上线,向服务器通知并注册。
2、同局域网下,所有注册用户可以进行群聊。
3、同局域网下,所有用户可与任意已注册用户进行私聊。
4、用户下线,通知服务器,服务器更新信息。
实现原理:
1、服务器端实例化一个ServerSocket对象,调用accept方法等待客户端连接到服务器。
2、客户端实例化 Socket 对象,并使用构造方法与服务器建立链接。
3、服务器端根据客户端输入信息,辨别客户端请求的功能从而做出相应响应。
实用技术:
为了能够高效的处理客户端的请求,在服务器端使用多线程处理客户端请求。并且使用 ConcurrentHashMap 来存储所有注册过的客户端。
项目源码(解释写在代码的注释当中):
服务器端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
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.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ManyThreadServer { //存储所有注册的客户端 private static Map<String, Socket> clientMap = new ConcurrentHashMap<String,Socket>(); //具体的处理每个客户端的请求 private static class ExcuteClient implements Runnable{ private Socket client; public ExcuteClient(Socket client) { this .client = client; } @Override public void run() { try { //获取客户端的输出流,读取客户端消息,并处理 Scanner in = new Scanner(client.getInputStream()); String strFromClient; while ( true ){ if (in.hasNextLine()){ strFromClient = in.nextLine(); //在Windows下默认换行是:\r\n,所以把\r要转换为空字符串 Pattern pattern = Pattern.compile( "\r" ); Matcher matcher = pattern.matcher(strFromClient); strFromClient = matcher.replaceAll( "" ); //注册流程 if (strFromClient.startsWith( "useName" )){ String useName = strFromClient.split( "\\:" )[ 1 ]; registerUser(useName,client); continue ; } //群聊功能 if (strFromClient.startsWith( "G" )){ String msg = strFromClient.split( "\\:" )[ 1 ]; groupChat(msg,client); continue ; } //私聊功能 if (strFromClient.startsWith( "P" )){ String userName = strFromClient.split( "\\:" )[ 1 ].split( "-" )[ 0 ]; String msg = strFromClient.split( "\\:" )[ 1 ].split( "-" )[ 1 ]; privateChat(userName,msg,client); continue ; } //用户退出 if (strFromClient.startsWith( "B" )){ String userName = null ; //根据Socket找到UserName for (String keyName : clientMap.keySet()){ if (clientMap.get(keyName).equals(client)){ userName = keyName; } } System.out.println( "用户" + userName + "下线了。。。" ); clientMap.remove(userName); System.out.println( "当前共有用户" + clientMap.size() + "人" ); continue ; } else { PrintStream out = new PrintStream(client.getOutputStream(), true , "UTF-8" ); out.println( "输入错误。。。" ); } } } } catch (IOException e) { e.printStackTrace(); } } private void registerUser(String name,Socket client){ System.out.println( "用户:" + name + "已上线!" ); clientMap.put(name,client); System.out.println( "当前在线人数:" + clientMap.size() + "人!" ); //既然是用户在注册,所以这里服务器通知用户注册结果 try { PrintStream out = new PrintStream(client.getOutputStream(), true , "UTF-8" ); out.println( "用户注册成功!" ); } catch (IOException e) { e.printStackTrace(); } } private void groupChat(String msg,Socket client){ //取出clientMap中所有的Entry对象,遍历每个用户,并且发送消息 Set<Map.Entry<String,Socket>> clientSet = clientMap.entrySet(); for (Map.Entry<String,Socket> entry:clientSet){ try { Socket socket = entry.getValue(); //取得输出流,向客户端发送消息 PrintStream out = new PrintStream(socket.getOutputStream(), true , "UTF-8" ); out.println( "由端口号为" + client.getPort() + "发来的群聊消息:" + msg); } catch (IOException e) { e.printStackTrace(); } } } private void privateChat(String userName,String msg,Socket client){ Socket privateSocket = clientMap.get(userName); try { PrintStream out = new PrintStream(privateSocket.getOutputStream(), true , "UTF-8" ); out.println( "由端口号为:" + client.getPort() + "发来的消息:" + msg); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws Exception{ //为了提高效率,这里使用多线程进行处理 ExecutorService executorService = Executors.newFixedThreadPool( 30 ); //实例化ServerSocket对象,并指定IP为本地主机,端口号为6666 ServerSocket serverSocket = new ServerSocket( 6666 ); for ( int i = 0 ; i < 30 ;i++){ System.out.println( "等待用户连接。。。" ); //等待客户端连接服务器 Socket client = serverSocket.accept(); System.out.println( "有客户端连接,端口号为:" + client.getPort()); //启动线程,并处理客户端请求 executorService.submit( new ExcuteClient(client)); } //关闭线程,关闭服务器 executorService.shutdown(); serverSocket.close(); } } |
客户端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
import java.io.IOException; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; /** * 接收服务端发来的消息 */ class FromServer implements Runnable{ Socket client; public FromServer(Socket client){ this .client = client; } @Override public void run() { try { Scanner in = new Scanner(client.getInputStream()); while ( true ) { if (in.hasNextLine()) { System.out.println( "服务器:" + in.nextLine()); } //判断客户端是否退出,如果推出,跳出循环,并关闭流 if (client.isClosed()) { System.out.println( "客户端关闭。。。" ); break ; } } in.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 向服务端发出消息 */ class ToServer implements Runnable{ Socket client; public ToServer(Socket client){ this .client = client; } @Override public void run() { try { Scanner scanner = new Scanner(System.in); PrintStream out = new PrintStream(client.getOutputStream(), true , "UTF-8" ); while ( true ) { System.out.println( "请输入信息:" ); String strToserver; if (scanner.hasNextLine()){ strToserver = scanner.nextLine().trim(); out.println(strToserver); //客户端退出标志:B if (strToserver.startsWith( "B" )){ System.out.println( "客户端退出。。。" ); scanner.close(); out.close(); client.close(); break ; } } } } catch (IOException e) { e.printStackTrace(); } } } public class ManyThreadClient { public static void main(String[] args){ try { //实例化Socket对象,与服务器建立连接 Socket client = new Socket( "127.0.0.1" , 6666 ); //为了发送消息和接收消息可以同时进行,使用多线程进行处理 Thread thread1 = new Thread( new FromServer(client)); Thread thread2 = new Thread( new ToServer(client)); thread1.start(); thread2.start(); } catch (IOException e) { e.printStackTrace(); } } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/weixin_41890097/article/details/82384039