Java Socket + Multithreading to Realize Multi person Chat Room Function
- 2021-11-01 03:06:33
- OfStack
This article example for everyone to share Java Socket + multi-threaded implementation of multi-person chat room specific code, for your reference, the specific content is as follows
Brief introduction of ideas
It is divided into two classes: client and server. All the clients send the chat content to the server. After the server accepts it, it sends every one content to every one client, and the client displays it on the terminal.
Client design
Client contains two threads, one for receiving server information, then display, one for receiving keyboard input, sent to the server.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class WeChatClient { //WeChat Client class of
private Socket client;
private String name;
private InputStream in;
private OutputStream out;
private MassageSenter massageSenter;
private MassageGeter massageGeter;
class MassageGeter extends Thread{ //1 Child thread class for clients to receive messages
MassageGeter() throws IOException{
in = client.getInputStream();
}
@Override
public void run() {
int len;
byte[] bytes = new byte[1024];
try {
while ((len = in.read(bytes)) != -1) { // This function is blocked
System.out.println(new String(bytes,0,len, StandardCharsets.UTF_8));
}
}catch (IOException e){
System.out.println(e.toString());
}
System.out.println("Connection interruption");
}
}
class MassageSenter extends Thread{ //1 Child thread class, which is used to send messages to the server
MassageSenter() throws IOException{
out = client.getOutputStream();
}
@Override
public void run() {
Scanner scanner = new Scanner(System.in);
try {
while (scanner.hasNextLine()) { // This function is a blocked function
String massage = scanner.nextLine();
out.write((name + " : " + massage).getBytes(StandardCharsets.UTF_8));
if(massage.equals("//exit"))
break;
}
}catch (IOException e){
e.printStackTrace();
}
}
}
WeChatClient(String name, String host, int port) throws IOException {// Initialize, instantiate send and receive 2 Threads
this.name = name;
client = new Socket(host,port);
massageGeter = new MassageGeter();
massageSenter = new MassageSenter();
}
void login() throws IOException{// When logging in, send the name to the server first, and start the thread after receiving the correct response from the server
out.write(name.getBytes(StandardCharsets.UTF_8));
byte[] bytes = new byte[1024];
int len;
len = in.read(bytes);
String answer = new String(bytes,0,len, StandardCharsets.UTF_8);
if(answer.equals("logined!")) {
System.out.println("Welcome to WeChat! "+name);
massageSenter.start();
massageGeter.start();
try {
massageSenter.join();//join() The function of is to wait for the thread to finish before continuing to execute the main thread (main)
massageGeter.join();
}catch (InterruptedException e){
System.err.println(e.toString());
}
}else{
System.out.println("Server Wrong");
}
client.close();
}
public static void main(String[] args) throws IOException{// Program entry
String host = "127.0.0.1";
WeChatClient client = new WeChatClient("Uzi",host,7777);
client.login();
}
}
Server design
The server consists of three thread classes: port listening thread, client receiving information thread and sending information thread.
The server class also contains and maintains a list of connected users and a list of messages to be sent.
The server has a thread responsible for listening to the port, which adds the connected client to the user list after receiving the connection request from the client; And instantiate one thread class for each connected client to receive information from each client and store it in the list of information to be sent.
The thread of sending information checks whether the list is empty, and if it is not empty, it sends the information inside to every 1 user in the user list.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class WeChatServer {
private ServerSocket server;
private ArrayList<User> users;// User list
private ArrayList<String> massages;// Message queue to be sent
private Listener listener;
private MassageSenter massageSenter;
class User{ // User class, which contains the login of the user id And 1 Output streams
String name;
OutputStream out;
User(String name,OutputStream out){
this.name = name;
this.out = out;
}
@Override
public String toString() {
return name;
}
}
private static String GetMassage(InputStream in) throws IOException{// From 1 Input stream reception 1 String
int len;
byte[] bytes = new byte[1024];
len = in.read(bytes);
return new String(bytes,0,len,StandardCharsets.UTF_8);
}
private void UserList(){ // List the current online users for debugging
for(User user : users)
System.out.println(user);
}
class Listener extends Thread{ // Listen to the thread class, and if it is negative, listen to whether there is a client connection
@Override
public void run() {
try {
while (true) {
Socket socket = server.accept();// This function is blocked
InputStream in = socket.getInputStream();
String name = GetMassage(in);// Object of the access user name
System.out.println(name +" has connected");
massages.add(name+" has joined just now!!");// Report the information connected by the user to the chat room
OutputStream out = socket.getOutputStream();
out.write("logined!".getBytes(StandardCharsets.UTF_8));// Send feedback that the connection was successfully established
User user = new User(name,out);
users.add(user);// Add to Online Users List
MassageListener listener = new MassageListener(user,in);// Create a thread to receive this user information
listener.start();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
class MassageListener extends Thread{ // The receiving thread class is used from the 1 Clients receive information and add it to the list to be sent
private User user;
private InputStream in;
MassageListener(User user,InputStream in){
this.user = user;
this.in = in;
}
@Override
public void run() {
try {
while (true){
String massage = GetMassage(in);
System.out.println("GET MASSAGE "+massage);
if(massage.contains("//exit")){ // "/exit" Is an exit command
break;
}
massages.add(massage);
}// There are two forms of user exit, and enter " //exit " Or close the program directly
in.close();
user.out.close();
}catch (IOException e){// This exception is to handle the abnormal shutdown of the client, that is GetMassage(in) Call throws an exception because in The incoming and outgoing flow has been automatically closed
e.printStackTrace();
}finally {
System.out.println(user.name+" has exited!!");
massages.add(user.name+" has exited!!");
users.remove(user);// You must remove the disconnected user from the user list, or an exception will be generated when sending information
System.out.println("Now the users has");
UserList();
}
}
}
private synchronized void SentToAll(String massage)throws IOException{// Send information to every 1 Users, join synchronized Decoration to ensure that the user list will not be changed by other threads when sending
if(users.isEmpty())
return;
for(User user : users){
user.out.write(massage.getBytes(StandardCharsets.UTF_8));
}
}
class MassageSenter extends Thread{// Message sending thread
@Override
public void run() {
while(true){
try{
sleep(1);// There are no blocked functions in this thread, and sleep statements are added to prevent the thread from preempting resources too much
}catch (InterruptedException e){
e.printStackTrace();
}
if(!massages.isEmpty()){
String massage = massages.get(0);
massages.remove(0);
try {
SentToAll(massage);
}catch (IOException e){
e.printStackTrace();
}
}
}
}
}
WeChatServer(int port) throws IOException { // Initialization
server = new ServerSocket(port);
users = new ArrayList<>();
massages = new ArrayList<>();
listener = new Listener();
massageSenter = new MassageSenter();
}
private void start(){ // Thread startup
listener.start();
massageSenter.start();
}
public static void main(String[] args) throws IOException{
WeChatServer server = new WeChatServer(7777);
server.start();
}
}
Summarize
Multithreaded programming is required because some functions are blocked, such as
while ((len = in.read(bytes)) != -1) { // This function is blocked
System.out.println(new String(bytes,0,len, StandardCharsets.UTF_8));
}
while (scanner.hasNextLine()) { // This function is a blocked function
String massage = scanner.nextLine();
out.write((name + " : " + massage).getBytes(StandardCharsets.UTF_8));
if(massage.equals("//exit"))
break;
}
Socket socket = server.accept();// This function is blocked
These blocked functions need to wait for other programs. For example, scanner. hasNextLine () needs to wait for the programmer's input before returning values. in. read needs to wait for the other side of the stream to transmit data. Using multithreading can run other threads when these functions are blocked.
Therefore, the key to multithreaded programming is those blocking functions.