Catalog
3、 ... and 、 Group chat core method
Four 、 Chat room specific design
1、 Check the current online users
4、 Exit the current chat status
5、 ... and 、 Chat room service complete code
6、 ... and 、 Effect demonstration : be based on TCP Online real-time chat room
Come to the point
In the last month, I recorded my study Socket Network programming knowledge and practical cases , relatively speaking , More systematically Learning based on TCP The protocol realizes network communication , It's also the top priority in computer networks ,TCP/IP It belongs to the network layer , stay java in , The work of this layer is encapsulated , In programming , It's easier to communicate , Without regard to the underlying implementation . Of course , We need to be familiar with the five tier protocol , Experience the principle in practice , Deeper understanding .
therefore , The series begins with an introduction , Continuously improve C/S Architecturally Socket signal communication , recall , First of all, it has realized Server and Client To communicate with each other , Find problems in the process , Then we use multithreading technology to solve the problem of receiving information in real time , And then it came to the server side , Find multi-user connections to the server “ First come first served basis ” problem ,“ Late comer ” Unable to communicate properly , So we use thread pool technology to solve the problem of multi-user server .
Here we are , The basic implementation of a simple client - Server applications , therefore , This article will be based on all the previous content , Using client - The server (C/S framework ), Combined with multithreading technology , Simulation similar QQ、 Wechat chat function , Realize a network real-time chat room , Current features include :
(1)L(list): Check the current online users ;
(2)G(group): Group chat ;
(3)O(one-one): Direct messages ;
(4)E(exit): Exit the current chat status ;
(5)bye: offline ;
(6)H(help): view help
This article will record in detail the implementation steps of network real-time chat room , Based on the following series of articles .
Java Realization socket Communication network programming series article :
- be based on UDP Protocol network Socket Programming (java Realization C/S Communication cases )【https://blog.csdn.net/Charzous/article/details/109016215】
- be based on TCP Protocol network socket Programming (java Realization C/S signal communication )【https://blog.csdn.net/Charzous/article/details/109016215】
- Java Multithreaded implementation TCP The Internet Socket Programming (C/S signal communication )【https://blog.csdn.net/Charzous/article/details/109283697】
- Java Multithreading realizes multi-user and server side Socket signal communication 【https://blog.csdn.net/Charzous/article/details/109440277】
One 、 data structure Map
The first two articles TCPClientThreadFX and TCPThreadServer Multi thread communication is realized , But it's just a chat between the client and the server , How to do group chat ? The idea is the customer A The chat information is forwarded to all customers online at the same time through the server .
It is necessary to In the server-side new record login customer information The function of , Each user has its own logo . This article will use the simple “ Online mode ” Record client socket , That is to use the collection to save the user login Socket information , To track user connections .
therefore , We need to choose an appropriate data structure to hold the user's Socket And user name information , That's in java in , What data structures are provided ?
Java The common set types are :Map、List and Set.Map Is save Key-Value Yes ,List It's like an array , Repeatable values can be saved , and Set Save only non duplicate values , It's equivalent to saving only key, Do not save value Of Map.
If you have a user name 、 Operation of student number login , You can use Map A collection of types to store , For example, you can use key Record the user name + Student number ,value Save socket . about The demand of this article's network chat room , Need to adopt Map, To save different users socket And login name . User socket socket As key To identify an online user is a more convenient choice , Because every client has IP Address + Port combinations are different .
Two 、 Ensure thread safety
Obviously , We need to use multithreading technology , And in a multithreaded environment , There is a thread concurrency security problem in reading and writing shared resources , for example HashMap、HaspSet It's not thread safe , Can pass synchronized Key to lock , But there are more convenient solutions : You can use it directly Java Standard library java.util.concurrent Package provides a collection of thread safe . for example HashMap The thread safety of is ConcurrentHashMap,HashSet Thread safety for Set yes CopyOnWriteArraySet.
Pictured ,Map Inheritance system :
stay JDK1.8 in , Yes HashMap Improved , When the number of nodes exceeds TREEIFY_THRESHOLD
It's going to turn into a red black tree , This greatly optimizes the efficiency of the query , But it's still not thread safe .
Here's a quick look at , Specific learning can query relevant information . With the above basic knowledge , The following start to enter the specific implementation of the network real-time chat room .
3、 ... and 、 Group chat core method
Based on the idea above : The realization of group chat is the customer A The chat information is forwarded to all customers online at the same time through the server , Server side according to HashMap Record the login user's socket, Forward information to all users .
The core group sending method sendToAllMembers, Used to send messages to all online customer service .
private void sendToMembers(String msg,String hostAddress,Socket mySocket) throws IOException{
PrintWriter pw;
OutputStream out;
Iterator iterator=users.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry entry=(Map.Entry) iterator.next();
Socket tempSocket = (Socket) entry.getKey();
String name = (String) entry.getValue();
if (!tempSocket.equals(mySocket)){
out=tempSocket.getOutputStream();
pw=new PrintWriter(new OutputStreamWriter(out,"utf-8"),true);
pw.println(hostAddress+":"+msg);
}
}
}
Using the Map The traversal , Send messages to all other users .
The same principle , We realize the function of private chat , The idea of transformation into realization , That is, the current user and the designated user Socket Communication between , So I wrote a sendToOne Methods .
private void sendToOne(String msg,String hostAddress,Socket another) throws IOException{
PrintWriter pw;
OutputStream out;
Iterator iterator=users.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry entry=(Map.Entry) iterator.next();
Socket tempSocket = (Socket) entry.getKey();
String name = (String) entry.getValue();
if (tempSocket.equals(another)){
out=tempSocket.getOutputStream();
pw=new PrintWriter(new OutputStreamWriter(out,"utf-8"),true);
pw.println(hostAddress+" I wrote to you :"+msg);
}
}
}
The above two methods are the key of this network chat room , The later function will be the flexible application of these two methods .
Four 、 Chat room specific design
At present, the function orientation of chat room includes :1) Check the current online users ;2): Group chat ;3) Direct messages ;4) Exit the current chat status ;5) offline ;6) view help .
First , Initialize the most critical data structure , As a class member variable ,HashMap For preservation Socket And the user name :
private ConcurrentHashMap<Socket,String> users=new ConcurrentHashMap();
Each function is implemented as follows :
0、 Users log on to the server
Here is the first server side information processing , You need to record each user's login information , Includes the connected socket and a custom nickname , Convenient for subsequent use . My approach is when users connect to the server , Remind the user to enter the user name for further operation , It also realizes the judgment logic of non duplicate names . The code is as follows :
pw.println("From The server : Welcome to the service !");
pw.println(" Please enter a user name :");
String localName = null;
while ((hostName=br.readLine())!=null){
users.forEach((k,v)->{
if (v.equals(hostName))
flag=true;// Thread changes global variables
});
if (!flag){
localName=hostName;
users.put(socket,hostName);
flag=false;
break;
}
else{
flag=false;
pw.println(" The user name already exists , Please amend !");
}
}
After successful login, all online users will be informed of the online information .
1、 Check the current online users
In fact, it records the server in HashMap The information in is returned to the requesting user , By an agreed order L Check it out. :
if (msg.trim().equalsIgnoreCase("L")){
users.forEach((k,v)->{
pw.println(" user :"+v);
});
continue;
}
2、 Group chat
else if (msg.trim().equals("G")){
pw.println(" You have entered group chat .");
while ((msg=br.readLine())!=null){
if (!msg.equals("E")&&users.size()!=1)
sendToMembers(msg,localName,socket);
else if (users.size()==1){
pw.println(" Currently, there are no other users online , Automatically exited !");
break;
}
else {
pw.println(" You have exited group chat !");
break;
}
}
}
3、 Direct messages
Empathy , Processing logic becomes one-to-one communication , With previous servers - It's like a one-to-one client , But there's a lot more to deal with here , Make sure the logic is correct , Including the online status of the person being chatted with in private , Whether the user name of the private talker is correct .
// One on one private chat
else if (msg.trim().equalsIgnoreCase("O")){
pw.println(" Please enter the user name of the private party :");
String name=br.readLine();
// lookup map Match in socket, Establish communication with it
// To be improved , Handle the case that the entered user name does not exist
users.forEach((k, v)->{
if (v.equals(name)) {
isExist=true;// Global variables and thread modification
}
});
// Fixed processing logic where the user does not exist
Socket temp=null;
for(Map.Entry<Socket,String> mapEntry : users.entrySet()){
if(mapEntry.getValue().equals(name))
temp = mapEntry.getKey();
// System.out.println(mapEntry.getKey()+":"+mapEntry.getValue()+'\n');
}
if (isExist){
isExist=false;
// After the private message, one user left , The other side is unknown , Still sending messages without receiving a reply , This situation has not been dealt with
while ((msg=br.readLine())!=null){
if (!msg.equals("E")&&!isLeaved(temp))
sendToOne(msg,localName,temp);
else if (isLeaved(temp)){
pw.println(" The other party has left , Disconnected connection !");
break;
}
else{
pw.println(" You have exited private message mode !");
break;
}
}
}
else
pw.println(" The user doesn't exist !");
}
4、 Exit the current chat status
This function is mainly integrated into group chat and private chat , We can see the internal calls of the above two functions , Defines a method isLeaved, Judge whether the user is offline .
// Judge whether the user is offline
private Boolean isLeaved(Socket temp){
Boolean leave=true;
for(Map.Entry<Socket,String> mapEntry : users.entrySet()) {
if (mapEntry.getKey().equals(temp))
leave = false;
}
return leave;
}
5、 offline
This function is relatively simple , To execute by an agreed order .
if (msg.trim().equalsIgnoreCase("bye")) {
pw.println("From The server : The server has been disconnected , End of service !");
users.remove(socket,localName);
sendToMembers(" I'm offline ",localName,socket);
System.out.println(" The client leaves .");// Add current user name
break;
}
6、 view help
Through the command H Ask for help from the server , It refers to the function of which commands the user views , To make a choice .
else if (msg.trim().equalsIgnoreCase("H")){
pw.println(" Input command function :(1)L(list): Check the current online users ;(2)G(group): Enter the group chat ;(3)O(one-one): Direct messages ;(4)E(exit): Exit the current chat status ;(5)bye: offline ;(6)H(help): help ");
continue;// Return loop
}
5、 ... and 、 Chat room service complete code
The main work of chat room implementation lies in the server , Focus on the internal classes of server threading Hanler, The above is a detailed introduction to each function , Here is the complete code , Just based on the previous article , see Java Multithreading realizes multi-user and server side Socket signal communication .
Modify the server-side thread processing code :
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
// The local server console displays the user information of the client connection
System.out.println("New connection accept:" + socket.getInetAddress().getHostAddress());
try {
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
pw.println("From The server : Welcome to the service !");
pw.println(" Please enter a user name :");
String localName = null;
while ((hostName=br.readLine())!=null){
users.forEach((k,v)->{
if (v.equals(hostName))
flag=true;// Thread changes global variables
});
if (!flag){
localName=hostName;
users.put(socket,hostName);
flag=false;// It's possible to find inconsistencies
break;
}
else{
flag=false;
pw.println(" The user name already exists , Please amend !");
}
}
// System.out.println(hostName+": "+socket);
sendToMembers(" I'm online ",localName,socket);
pw.println(" Input command function :(1)L(list): Check the current online users ;(2)G(group): Enter the group chat ;(3)O(one-one): Direct messages ;(4)E(exit): Exit the current chat status ;(5)bye: offline ;(6)H(help): help ");
String msg = null;
// Users connect to the server online , Enter the chat selection state
while ((msg = br.readLine()) != null) {
if (msg.trim().equalsIgnoreCase("bye")) {
pw.println("From The server : The server has been disconnected , End of service !");
users.remove(socket,localName);
sendToMembers(" I'm offline ",localName,socket);
System.out.println(" The client leaves .");// Add current user name
break;
}
else if (msg.trim().equalsIgnoreCase("H")){
pw.println(" Input command function :(1)L(list): Check the current online users ;(2)G(group): Enter the group chat ;(3)O(one-one): Direct messages ;(4)E(exit): Exit the current chat status ;(5)bye: offline ;(6)H(help): help ");
continue;// Return loop
}
else if (msg.trim().equalsIgnoreCase("L")){
users.forEach((k,v)->{
pw.println(" user :"+v);
});
continue;
}
// One on one private chat
else if (msg.trim().equalsIgnoreCase("O")){
pw.println(" Please enter the user name of the private party :");
String name=br.readLine();
// lookup map Match in socket, Establish communication with it
users.forEach((k, v)->{
if (v.equals(name)) {
isExist=true;// Global variables and thread modification
}
});
// Fixed processing logic where the user does not exist
Socket temp=null;
for(Map.Entry<Socket,String> mapEntry : users.entrySet()){
if(mapEntry.getValue().equals(name))
temp = mapEntry.getKey();
}
if (isExist){
isExist=false;
// After the private message, one user left , The other side is unknown , Still sending messages without receiving a reply , This situation has not been dealt with
while ((msg=br.readLine())!=null){
if (!msg.equals("E")&&!isLeaved(temp))
sendToOne(msg,localName,temp);
else if (isLeaved(temp)){
pw.println(" The other party has left , Disconnected connection !");
break;
}
else{
pw.println(" You have exited private message mode !");
break;
}
}
}
else
pw.println(" The user doesn't exist !");
}
// Choose group chat
else if (msg.trim().equals("G")){
pw.println(" You have entered group chat .");
while ((msg=br.readLine())!=null){
if (!msg.equals("E")&&users.size()!=1)
sendToMembers(msg,localName,socket);
else if (users.size()==1){
pw.println(" Currently, there are no other users online , Automatically exited !");
break;
}
else {
pw.println(" You have exited group chat !");
break;
}
}
}
else
pw.println(" Please select chat status !");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6、 ... and 、 Effect demonstration : be based on TCP Online real-time chat room
First , Open multiple clients , The connection server begins to enter the communication state .
The following diagram shows several basic functions , You can see that three users have realized real-time communication and chat , Including group chat and private chat function . Other functions are left to you to explore .
Conclusion
The series begins with an introduction , Continuously improve C/S Architecturally Socket signal communication , recall , First of all, it has realized Server and Client To communicate with each other , Find problems in the process , Then we use multithreading technology to solve the problem of receiving information in real time , And then it came to the server side , Find multi-user connections to the server “ First come first served basis ” problem ,“ Late comer ” Unable to communicate properly , So we use thread pool technology to solve the problem of multi-user server .
This article basically realizes a simple client - Server applications , Using client - The server (C/S framework ), Combined with multithreading technology , Simulation similar QQ、 Wechat chat function , Realize a network real-time chat room .
The knowledge learned is : Multithreading 、 Thread pool 、Socket signal communication 、TCP agreement 、HashMap、JavaFX etc. , The combination of all knowledge , And through actual combat practice , Understand knowledge step by step !
If you think it's good, welcome to “ One key, three links ” Oh , Like, collect, pay attention to , Comment directly if you have questions , Communication and learning !
Java Realization socket Communication network programming series article :
- be based on UDP Protocol network Socket Programming (java Realization C/S Communication cases )【https://blog.csdn.net/Charzous/article/details/109016215】
- be based on TCP Protocol network socket Programming (java Realization C/S signal communication )【https://blog.csdn.net/Charzous/article/details/109016215】
- Java Multithreaded implementation TCP The Internet Socket Programming (C/S signal communication )【https://blog.csdn.net/Charzous/article/details/109283697】
- Java Multithreading realizes multi-user and server side Socket signal communication 【https://blog.csdn.net/Charzous/article/details/109440277】
my CSDN Blog :https://blog.csdn.net/Charzous/article/details/109540279