catalogue
I. Introduction
Readers can understand the code and self-made by mastering the basic knowledge of multithreading, io flow and network programming. It is very easy to understand and learn. Those who do not understand individual code can also find information on the Internet. The source code will be attached later. I hope you can gain something
Second, write source code
2.1 create server and client
There must be at least two servers for communication. Here, in order to facilitate testing, two projects are established, and then exported for observation. Readers can directly establish two packages, which can be implemented as well, and even add or modify some functions on my basis
public class MyServer { //Server public static void main(String[] args) throws Exception {//Throw exception //Create listening port ServerSocket ss=new ServerSocket(8998);//The port must be consistent and cannot be duplicate with the existing port of the computer //Call the accept method of the listening port object to receive the connection request from the client Socket socket;//The following should receive an accept method to receive client information. I put it below
public class MyClient { //client public static void main(String[] args) throws Exception { //Create a socket object and request to connect to the remote server Socket socket=new Socket("localhost",8998);//Native and port
TCP triple handshake process
1. Host A sends A data segment containing the flag bit of the synchronization serial number to host B and requests host B to establish A connection. Through this data segment, host A tells host B two things: I want to communicate with you; Which serial number can you use as the starting data segment to respond to me
//Send message to client boolean flag=true; Scanner input=new Scanner(System.in); while(true) { while(flag) { System.out.println("Protocol: group chat prefix“ all:"Private chat "person name:", login“ login: ""); flag=false; } System.out.println("Please enter a message:"); String message=input.next(); byte[] buffer=message.getBytes(); //Use the output stream to send messages to the server OutputStream os=socket.getOutputStream(); os.write(buffer);
2 after receiving the request from host A, host B responds to host A with A data segment with acknowledgement (ACK) and synchronization serial number (SYN) flag bits, and also tells host A two things: I have received your request, and you can transmit data; Which serial number do you want to use as the starting data segment to respond to me
while(true){ System.out.println("Ready to receive client connections"); socket=ss.accept();//Responsible for communicating with connected customers System.out.println("A client is connected:"+socket.getRemoteSocketAddress()); //Create a thread that can receive port requests and messages at the same time ServerRecive sr=new ServerRecive(socket); sr.start(); }
3 after receiving this data segment, host A sends A confirmation response to confirm that it has received the data segment of host B: "I have received the reply, and I will start transmitting the actual data now. In this way, the three handshakes are completed, and host A and host B can transmit data
//Create a thread to receive server replies ClientReceiver cr=new ClientReceiver(socket); cr.start();
I only use one thread here. You can also consider using two threads
2.3 create function
Chat is generally divided into group chat and private chat, so we should have these two functions, but how to distinguish group chat and private chat? QQ is distinguished by @ all members and @ personal nicknames. We can also make a similar agreement and make a function to distinguish them,
Here is a login function without password
while(true) { //Judge whether the current user is logged in String address=socket.getRemoteSocketAddress().toString(); InputStream is = socket.getInputStream(); byte[] buffer=new byte[1024]; int r=is.read(buffer); String mess=new String(buffer,0,r); int i=0; if(mess.startsWith("login:")) { UserManager.login(address, new Customer(mess.split(":")[1], socket)); OutputStream os=socket.getOutputStream(); byte[] reply="Login succeeded".getBytes(); os.write(reply); else { OutputStream os=socket.getOutputStream(); byte[] reply="Please log in first".getBytes(); os.write(reply); }} //Log login information into the map collection public static void login(String address, Customer customer) { users.put(address, customer); }
Then there is the distinction between group chat and private chat
if(UserManager.checkLogin(address)) { String[] s=mess.split(":");//mess stores the information transmitted by the client //by the advices //Judge group chat or private hair if(s[0].equals( "all")) {//This means that the prefix is all: Collection<Customer> users=UserManager.getAllCustomer();//Get everyone's information, create a class, which stores the user name and address System.out.println("Now there are"+users.size()+"People online"); for (Customer customer : users) {//Traverse and pass on what you say to everyone if(!(customer.getUsername().equals(UserManager.getUsername(address).getUsername()))) { OutputStream os=customer.getSocket().getOutputStream(); byte[] messages=(UserManager.getUsername(address).getUsername()+ "say:"+s[1]).getBytes(); os.write(messages); }//Ignore yourself } }else { //Obtain the socket corresponding to the user from the map set according to the user name to which the message is to be forwarded Socket target=UserManager.getSocketByUsername(s[0]); OutputStream os=target.getOutputStream(); byte[] messages=(UserManager.getUsername(address).getUsername()+ "To you:"+s[1]).getBytes(); os.write(messages); }
Three renderings
IV. summary
It's easy. It's done all at once. The code is a process of continuous writing. I hope readers can write it several times to deepen their understanding. copy alone is useless. There are too many details to pay attention to. An carelessness is a series of bug s. For example, English symbols should be used in the middle of the test
V. source code
package qqserver; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class ServerRecive extends Thread { //Server processing thread private Socket socket; public ServerRecive(Socket socket) { super(); this.socket = socket; } @Override public void run() { //Receive messages from clients try { while(true) { //Judge whether the current user is logged in String address=socket.getRemoteSocketAddress().toString(); InputStream is = socket.getInputStream(); byte[] buffer=new byte[1024]; int r=is.read(buffer); String mess=new String(buffer,0,r); int i=0; if(mess.startsWith("login:")) { UserManager.login(address, new Customer(mess.split(":")[1], socket)); OutputStream os=socket.getOutputStream(); byte[] reply="Login succeeded".getBytes(); os.write(reply); }else { if(UserManager.checkLogin(address)) { String[] s=mess.split(":"); //by the advices //Judge group chat or private hair if(s[0].equals( "all")) { Collection<Customer> users=UserManager.getAllCustomer(); System.out.println("Now there are"+users.size()+"People online"); for (Customer customer : users) { if(!(customer.getUsername().equals(UserManager.getUsername(address).getUsername()))) { OutputStream os=customer.getSocket().getOutputStream(); byte[] messages=(UserManager.getUsername(address).getUsername()+ "say:"+s[1]).getBytes(); os.write(messages); } } }else { //Obtain the socket corresponding to the user from the map set according to the user name to which the message is to be forwarded Socket target=UserManager.getSocketByUsername(s[0]); OutputStream os=target.getOutputStream(); byte[] messages=(UserManager.getUsername(address).getUsername()+ "To you:"+s[1]).getBytes(); os.write(messages); } //System.out.println(UserManager.getUsername(address) + "say" + MES); }else { OutputStream os=socket.getOutputStream(); byte[] reply="Please log in first".getBytes(); os.write(reply); }} } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class UserManager{ //Save all logged in user information private static Map<String, Customer> users=new HashMap<String, Customer>(); //Log login information into the map collection public static void login(String address, Customer customer) { users.put(address, customer); } //Judge whether the user logs in public static boolean checkLogin(String address) { return users.containsKey(address); } //Return user name according to address public static Customer getUsername(String address) { return users.get(address); } //Obtain the corresponding socket according to the user name public static Socket getSocketByUsername(String username) { Collection<Customer> customers=users.values() ; Socket target =null; for (Customer customer : customers) { if(customer.getUsername().equals(username)) { target=customer.getSocket(); } } return target; } //Return all logged in users public static Collection<Customer> getAllCustomer() { return users.values(); } }
package qqserver; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; import sun.applet.Main; public class MyServer { public static void main(String[] args) throws Exception { //Create listening port ServerSocket ss=new ServerSocket(8998); //Call the accept method of the listening port object to receive the connection request from the client Socket socket; while(true){ System.out.println("Ready to receive client connections"); socket=ss.accept();//Responsible for communicating with connected customers System.out.println("A client is connected:"+socket.getRemoteSocketAddress()); //Create a thread that can receive port requests and messages at the same time ServerRecive sr=new ServerRecive(socket); sr.start(); } } }
package qqclient; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class MyClient { public static void main(String[] args) throws Exception { //Create a socket object and request to connect to the remote server Socket socket=new Socket("localhost",8998); //Create a thread to receive server replies ClientReceiver cr=new ClientReceiver(socket); cr.start(); //Send message to client boolean flag=true; Scanner input=new Scanner(System.in); while(true) { while(flag) { System.out.println("Protocol: group chat prefix“ all:"Private chat "person name:", login“ login: ""); flag=false; } System.out.println("Please enter a message:"); String message=input.next(); byte[] buffer=message.getBytes(); //Use the output stream to send messages to the server OutputStream os=socket.getOutputStream(); os.write(buffer); } } } class ClientReceiver extends Thread{ private Socket socket; public ClientReceiver(Socket socket) { super(); this.socket = socket; } @Override public void run() { try { while(true) { InputStream in=socket.getInputStream(); byte[] buffer=new byte[1000]; int r=in.read(buffer); System.out.println(new String(buffer,0,r)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package qqserver; import java.net.Socket; public class Customer { private String username; private Socket socket; public Customer(String username, Socket socket) { super(); this.username = username; this.socket = socket; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } }