Java learning punch in: on the 31st and 2nd day [complete the socket chat room construction project]
Java cultivation program (punch in day 31 and day 2)
Content management: implementation of Sockect chat room The Java interface uses various components. Don't worry about what you don't know about this part. It's OK to master one at presentProject demand analysis
The interface and function of a simple chat tool need to be completed to realize the communication between multiple clients under the server transfer. The functions completed by the system are
- After the program is started, you can see which machines are currently online, and a dialogue and chat box can pop up, in which you can edit the chat information to be sent and send it
- Once a machine in the network goes online, it can be notified immediately and the user list of the user interface can be updated
- When you double-click a list item, a dialogue and chat box will pop up, in which you can edit the information to be sent and send it
- The chat interface is user-friendly. The following is the sending box. There are existing chat records on it, and all chat records of the current time can be seen with the help of the scroll bar
- When someone sends a message to the machine, it can display the information received by the user, show who sent it, and reply to the information at the same time
Basic analysis
First of all, this is a chat tool. It uses the C/S structure. To simulate, you need to use net's Scott and ServerSocket to simulate the client and server
A variety of knowledge has been comprehensively used here. It is no longer a simple java SE knowledge, in which interface programming occupies the main code. Here you can paste a few pictures to see the effect. It took me two days to finish it, and the connection of polymorphic devices can be realized here
Divided into 3 packages
Sever package is mainly the relevant code of the server, which mainly realizes the interaction with users
Dao package is a simulated database package, which stores all user information and realizes the operation of addition, deletion and modification
Client is the client code package. As long as the code here is run on the computer, the client interface can appear, and the communication can be realized after the ip and port number are agreed. The client software is really realized here, but the software function is simple, and another architecture can be realized by web programming
Let's take a look at the interface
Let's take a look at the communication between the client and the server
Project part code summary
Dao's linked list storage implementation
package Dao; /** * In order to simplify the demonstration program, there is no need to store the database, and the single linked list is used to complete various functions of the database * Test code must be written here to check whether various functions are available * At the beginning, I tested the add, del and find functions, but did not test the getCount function. There was a problem. Later, I suddenly released the test and found an error */ public class UserLinkList { private Node head; private int count; public boolean addUser(Node client) { if(head == null) {//The head node also stores data head = client; count++; return true; } else { Node p = head; for(;p.next != null;p = p.next); { p.next = client; count++; return true; } } } public int getCount() { return count; } public Node findUser(String name) { Node p = head; while(p != null )//p. Next! = null does not contain the last node { if(p.username.equals(name)) { return p; } p = p.next; } return null; } public Node findUser(int index) { int pos = 0; Node p = head; while(p != null&& pos < index) { p = p.next; pos++; } if(p != null&& pos == index) { return p; } return null; } public boolean delUser(Node client) {//After deletion, the length should also be reduced Node p = head; if(p.username.equals(client.username)) {//Delete header node head = head.next; count--; return true; } while(p != null) {//Forget the cycle if(p.next.username.equals(client.username)) { p.next = p.next.next; count--; return true; } p = p.next; } return false; } /** * Here you can set a display method for inspection */ public void display() { Node p = head; int pos = 1; while(p != null) { System.out.println("The first"+pos + "Users"+p.username); p = p.next; pos++; } } } /* public static void main(String[] args) {//After testing, it is found that there is no problem and can be used normally Node client1 = new Node(); client1.username = "Zhang San "; Node client2 = new Node(); client2.username = "Li Si "; Node client3 = new Node(); client3.username = "Wang Wu "; //Other items will not be tested. Anyway, this item can be tested UserLinkList userLinkList = new UserLinkList();//Automatic initialization userLinkList.addUser(client1); userLinkList.addUser(client2); userLinkList.addUser(client3); // userLinkList.display(); Node node = userLinkList.findUser(0); userLinkList.delUser(node); userLinkList.display(); System.out.println(userLinkList.getCount()); } */
Writing this code now should be very simple, and be careful to test it
ServerListen
Take a brief look at this monitoring thread, which can monitor whether the user is online
package Server; /** * @author OMEY-PC *The function of this program is to realize the threading of server listening. The run method uses client = new Node(); creates a client object, sets the interface through client.socket = server.accept, and uses client.input *output To create an input / output stream */ import java.io.*; import java.net.*; import Dao.*; //Connection data import javax.swing.*; public class ServerListen extends Thread{ ServerSocket server; JComboBox combobox; JTextArea textarea; JTextField textfield; UserLinkList userLinkList; Node client; ServerReceive recvThread; public boolean isStop; /** * User online and offline listening class of chat server */ public ServerListen(ServerSocket server,JComboBox combobox,JTextArea textarea,JTextField textField,UserLinkList userLinkList) { this.server = server; this.combobox = combobox; this.textarea = textarea; this.textfield = textField; this.userLinkList = userLinkList; isStop = false; } @Override public void run() { while(!isStop && !server.isClosed())//The service was not stopped { try { client = new Node(); client.socket = server.accept();//Used to refer to the connected client client.output = new ObjectOutputStream(client.socket.getOutputStream()); client.output.flush(); client.input = new ObjectInputStream(client.socket.getInputStream()); client.username = (String)client.input.readObject(); //Display prompt information combobox.addItem(client.username);//Change to user name userLinkList.addUser(client); textarea.append("user" + client.username+"go online"+"\n"); textfield.setText("Online users"+ userLinkList.getCount()+"people\n"); recvThread = new ServerReceive(textarea,textfield,combobox,client,userLinkList); recvThread.start();//Start thread }catch (Exception e) { e.printStackTrace(); } } } }
ServerReceive
The thread realizes the information interaction between the server and the user
package Server; /** * @author OMEY-PC *Class of server sending and receiving messages */ import java.net.ServerSocket; import javax.swing.*; import Dao.*; public class ServerReceive extends Thread{ JTextArea textarea;//Message display field JTextField textfield;//Text input field JComboBox combobox; //check box Node client;//user UserLinkList userLinkList; public boolean isStop; public ServerReceive(JTextArea textarea, JTextField textfield, JComboBox combobox, Node client, UserLinkList userLinkList) { this.textarea = textarea; this.textfield = textfield; this.combobox = combobox; this.client = client; this.userLinkList = userLinkList; isStop = false; } @Override public void run() { //Send a list of users to everyone sendUserList(); while(!isStop && !client.socket.isClosed()) { try {//Type, to whom, status, behavior, information String type = (String)client.input.readObject(); if(type.equalsIgnoreCase("Chat message")) { String toSomebody =(String)client.input.readObject();//Receive information from client String status = (String)client.input.readObject(); String action = (String)client.input.readObject(); String message = (String)client.input.readObject(); String msg = client.username+" "+ action + "yes"+ toSomebody +" say " + message + "\n";//Received messages if(status.equalsIgnoreCase("Whisper")) { msg = "[Whisper]" + msg; //If it's a whisper, put a sign in front of it } textarea.append(msg); if(toSomebody.equalsIgnoreCase("all")) { sendToAll(msg);//Here is the accepted user message, which is different from the previous message to everyone } else {//Send messages to users try { client.output.writeObject("Chat message"); client.output.flush();//Refresh stream client.output.writeObject(msg); client.output.flush(); }catch (Exception e) { e.printStackTrace(); } Node node = userLinkList.findUser(toSomebody); if(node != null) { node.output.writeObject("Chat message"); node.output.flush(); node.output.writeObject(msg);//Send message to selected message node.output.flush();//Flushes the information in the output stream buffer } } } else if(type.equalsIgnoreCase("User offline")) { Node node = userLinkList.findUser(client.username); userLinkList.delUser(node); String msg = "user"+ client.username +"Offline\n"; int count = userLinkList.getCount(); combobox.removeAllItems(); combobox.addItem("all"); int i = 0; while(i < count) { node = userLinkList.findUser(i); if(node == null) { i++; continue; } combobox.addItem(node.username); i++; } combobox.setSelectedIndex(0);//Choose the first, everyone textarea.append(msg); textfield.setText("Online users"+ userLinkList.getCount() +"people\n"); sendToAll(msg); sendUserList();//Resend user list break; } }catch (Exception e) { e.printStackTrace(); } } } /** * Send a message to everyone */ public void sendToAll(String msg) { int count = userLinkList.getCount(); int i = 0; while(i < count) {//Send a message to everyone in the user list Node node = userLinkList.findUser(i); if(node == null) { i++; continue; } try {//Output stream node.output.writeObject("Chat message"); node.output.flush(); node.output.writeObject(msg);//Chat message write output stream (to client) node.output.flush(); }catch (Exception e) { e.printStackTrace(); } i++; } } /** * Send user list to everyone */ public void sendUserList() { String userList = ""; int count = userLinkList.getCount(); int i = 0; while(i < count) { Node node = userLinkList.findUser(i); if(node == null) { i++; continue; } userList += node.username; userList += "\n"; i++; } i = 0; //Send a message to everyone while(i < count) { Node node = userLinkList.findUser(i); if(node == null) { i++; continue; } try { node.output.writeObject("User list"); node.output.flush(); node.output.writeObject(userList); node.output.flush(); }catch (Exception e) { e.printStackTrace(); } } i++; } } /** * This program can send messages and user lists to all people through threads, and send chat messages to selected people. It is mainly to realize the threading of sending and receiving messages at the server, in which sendUserList() sends lists, * client.input.redObject()Get the message sent by the client to the server, and send the information sent to everyone to each client through sendToAll() */
Take another look at the ClientReceive of the client
The thread realizes the information interaction between the client and the system, with rich annotations
package Client; import java.io.*; import java.net.*; import javax.swing.*; public class ClientReceive extends Thread{ private JComboBox combobox; private JTextArea textarea; Socket socket; ObjectOutputStream output; ObjectInputStream input; JTextField showStatus; public ClientReceive(JComboBox combobox, JTextArea textarea, Socket socket, ObjectOutputStream output, ObjectInputStream input, JTextField showStatus) { this.combobox = combobox; this.textarea = textarea; this.socket = socket; this.output = output; this.input = input; this.showStatus = showStatus; } @Override public void run() {//Get message from server while(!socket.isClosed()) { try { String type = (String)input.readObject();//Get the stream and read the information if(type.equalsIgnoreCase("system information ")) { String sysmsg = (String)input.readObject(); textarea.append("system information " + sysmsg); } else if(type.equalsIgnoreCase("Service shutdown")) { output.close(); input.close(); socket.close(); textarea.append("The server has been shut down!\n"); break; } else if(type.equalsIgnoreCase("Chat message")) { String message = (String)input.readObject(); textarea.append(message); } else if(type.equalsIgnoreCase("User list")) { String userlist = (String)input.readObject(); String[] usernames = userlist.split("\n"); //Separate with newline combobox.removeAll();//Move out first int i = 0; combobox.addItem("all"); while(i < usernames.length) { combobox.addItem(usernames[i]); i++; } combobox.setSelectedIndex(0); showStatus.setText("Online users"+ usernames.length +" people"); } }catch (Exception e) { e.printStackTrace(); } } } }
The rest of the interface will not be released. The code is too long. There are more than 400 lines each. If you are interested, you can browse my gitee and put the address behind it
Project issues
The user name does not appear in the selection box
Find the corresponding module. It is found that the node added in addItem is not the username in the node. It is normal after modification
The server does not respond when it clicks the send message button
Find the listener part. It is found that the listener listens to the wrong code in this part, and write the button as sysMessage
Online number cannot be displayed
Find the listening thread, start the client, and throw an exception
Cannot invoke "javax.swing.JTextField.setText(String)" because "this.textfield" is null
textfield is empty. Find the source of the problem. It is found in the construction method: the assignmen to variable has no effect. This is because the word is misspelled and the compiler does not report an error
There is no message when the server exits
System error
Cannot read field "input" because "node" is null
Realize that the problem lies in the linked list. The system requires that the serial number in the linked list start from 0, and the serial number in the linked list starts from 1. Fix the pos in findUser in the linked list to 0
After writing this program for two days, it was directly abandoned~~