Single threaded example
Realize function
For 1-to-1 chat communication between the server and the client, you need to run the server first and then the client. When the user enters bye, close the socket and terminate the chat.
Specific operation process
- Start the server, create a ServerSocket, block the accept method, and wait for the client to connect.
- Start the client and connect to the server.
- The server accepts the connection and gets the ServerSocket socket object returned by accept().
- The server side and the client side create their own threads to listen to messages, and then they can interact with each other through the input and output stream of the socket.
- When one party inputs bye, the socket is closed and disconnected
- Close relevant resources and the communication ends
code
Server side
//ServerDemo.java import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * @author Pure_vv * @date 2022/1/29 */ public class ServerDemo { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(SocketUtils.PORT); Socket socket = serverSocket.accept(); //Start receiving message thread new ReceiveMsg(socket).start(); //The main thread starts sending messages SocketUtils.sendMsg(socket, socket.getOutputStream()); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
client
//ClientDemo.java import java.io.IOException; import java.net.InetAddress; import java.net.Socket; /** * @author Pure_vv * @date 2022/1/29 */ public class ClientDemo { public static void main(String[] args) { try { Socket socket = new Socket(InetAddress.getLocalHost(),SocketUtils.PORT); //Receive message thread on new ReceiveMsg(socket).start(); //The main thread starts sending messages SocketUtils.sendMsg(socket, socket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } }
Encapsulated tool class
SocketUtils.java: encapsulates the method of sending user console input messages and defines port constants.
import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; /** * @author Pure_vv * @date 2022/2/4 */ public class SocketUtils { public static final int PORT = 8888; public static void sendMsg(Socket socket, OutputStream os){ PrintWriter pw = new PrintWriter(os); Scanner sc = new Scanner(System.in); String msg; while (!socket.isClosed() && (msg = sc.next())!=null){ // BufferedReader. The readline() method does not stop reading until it encounters \ n or \ r, which is a blocking method //Manually encapsulate messages and add \ n pw.write(msg+'\n'); pw.flush(); if ("bye".equals(msg)){ break; } } System.out.println("The message transmission is completed and the program ends"); try { os.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
ReceiveMsg.java: create a new thread to listen for information and print the information to the console
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; import java.net.SocketException; /** * @author Pure_vv * @date 2022/1/29 */ public class ReceiveMsg extends Thread { InputStream inputStream; Socket socket; public ReceiveMsg(Socket socket) { this.socket = socket; try { this.inputStream = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { System.out.println("Thread started"); //Byte stream character stream InputStreamReader isr = new InputStreamReader(inputStream); //Add buffered read data BufferedReader br = new BufferedReader(isr); try { String msg; //Print the message to the console when it is received while ((msg=br.readLine())!=null) { System.out.println("msg:"+msg); if ("bye".equals(msg)){ System.out.println("receive messages socket close"); socket.close(); break; } } } catch (IOException e) { if (!(e instanceof SocketException)){ e.printStackTrace(); } } } }
Multithreading example
Enable the server to support multiple client connections and chat
Just add a thread class and slightly change serverdemo java
//ServerDemo.java import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * @author Pure_vv * @date 2022/1/29 */ public class ServerDemo { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(SocketUtils.PORT); while (true){ Socket socket = serverSocket.accept(); // Start a new thread to listen for connection requests new ServerThread(socket).start(); } // new ReceiveMsg(socket).start(); // SocketUtils.sendMsg(socket, socket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } }
Added thread class serverthread java
import java.io.IOException; import java.net.Socket; /** * @author Pure_vv * @date 2022/2/5 */ public class ServerThread extends Thread{ Socket socket; public ServerThread(Socket socket) { this.socket = socket; } @Override public void run() { super.run(); //Start receiving message thread new ReceiveMsg(socket).start(); //The main thread starts sending messages try { SocketUtils.sendMsg(socket, socket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } }
reflection
What I don't quite understand:
-
Use PrintWriter to transmit messages (for example, from the server to the client). After the client's socket is closed, the server will not throw an exception when sending messages without understanding
-
Solution: the server closes the socket after receiving the bye and judges the socket when sending a message isClosed()
But at the same time, this will bring a problem. When chatting with a single thread, you can pay attention to the code of sending messages
while (!socket.isClosed() && (msg = sc.next())!=null){ pw.write(msg+'\n'); pw.flush(); if ("bye".equals(msg)){ break; } }
After the server is started, the accept method will be blocked. After the client is started, the codes of both sides will be blocked in sc.next(), socket Isclosed() returned false. At this time, either party enters bye to close the socket, and the other party needs to enter a line to finish completely.
- Possible solutions: realize event monitoring (observer mode) through the registration notification mechanism to monitor whether the socket is closed in real time. It needs to be implemented and verified
In addition, there is a problem. When using multithreading, it will cause confusion in chat. Two threads connecting to the client run concurrently, which will cause the server to need to input alternately.
reference material:
The Scanner class throws Java util. NoSuchElementException
java - use java net. Socket and java net. ServerSocket implements a simple chat program