Java advanced: real time chat room based on TCP (socket communication case)

osc_qcm2mqmy 2020-11-10 10:51:54
java advanced real time chat


Catalog

Come to the point

One 、 data structure Map

Two 、 Ensure thread safety

3、 ... and 、 Group chat core method

Four 、 Chat room specific design

0、 Users log on to the server

1、 Check the current online users

2、 Group chat

3、 Direct messages

4、 Exit the current chat status

5、 offline

6、 view help

5、 ... and 、 Chat room service complete code

6、 ... and 、 Effect demonstration : be based on TCP Online real-time chat room

Conclusion


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 :

  1. be based on UDP Protocol network Socket Programming (java Realization C/S Communication cases )https://blog.csdn.net/Charzous/article/details/109016215
  2. be based on TCP Protocol network socket Programming (java Realization C/S signal communication )https://blog.csdn.net/Charzous/article/details/109016215
  3. Java Multithreaded implementation TCP The Internet Socket Programming (C/S signal communication )https://blog.csdn.net/Charzous/article/details/109283697
  4. 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 :

  1. be based on UDP Protocol network Socket Programming (java Realization C/S Communication cases )https://blog.csdn.net/Charzous/article/details/109016215
  2. be based on TCP Protocol network socket Programming (java Realization C/S signal communication )https://blog.csdn.net/Charzous/article/details/109016215
  3. Java Multithreaded implementation TCP The Internet Socket Programming (C/S signal communication )https://blog.csdn.net/Charzous/article/details/109283697
  4. 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

版权声明
本文为[osc_qcm2mqmy]所创,转载请带上原文链接,感谢

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云