Beginners must understand! Use TCP or UDP to chat online!

Keywords: Java socket udp TCP/IP

Come on, this blog today teaches you how to write an online chat room by hand, and you can't cut me off.

1. Functional Design

  • Achieve online communication between two users without group functionality.

  • Keyboard entry

  • console output

2. Technical Analysis

  • The following analysis applies to both UDP and TCP
  1. First, we can easily write out two functions Send and Receive, one to listen for keyboard input and one to listen for connection input. How can we do this? Use a dead loop in each of these two functions to determine if the input is an end condition, jump out of the loop, close the connection, or listen all the time. This part of the code can see the attachment.
  2. So how do we get users to receive and send? Someone said we could let a user have both Send and Receive methods, and then let the user execute two methods separately! NONONONO!Too Yang Too Sen Broken! Things are not that simple, because the above uses a dead loop, so if you first execute the receive, it must not be sent, if you first send, it must not be received!
  3. From the analysis of 2, we have to synchronize the receive and send! That's right, it's multi-threaded!!! Let each user open two threads, keep receiving and sending, so that a connection can be established. Then just put the function in the run function.

3. Specific implementation

3.1. Implementation of UDP

//Send Method Implementation Class
package main.UdpChat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.*;

public class SendMessage implements Runnable {
    //Look primarily at the run method
    public int port;//Your own port name
    public int toPort;//To which port
    public String toIp;//To which address
    public  DatagramSocket socket = null;
    public BufferedReader reader = null;

    public SendMessage(int port, int toPort, String toIp) {
        this.port = port;
        this.toPort = toPort;
        this.toIp = toIp;

        try {
            socket = new DatagramSocket(curport);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        //Sender
        while(true)//Non-stop hair
        {
            try {
                reader  = new BufferedReader(new InputStreamReader(System.in));
                String data = reader.readLine();//Get the input, notice that there is no \n in the end of the data here, what is entered in the keyboard is what. Here the keyboard input is blocked, and when there is no input, it will wait here and not go down.
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas,0,datas.length,
                        new InetSocketAddress(toIp,toPort));//Pack

                socket.send(packet);//send attention! send here is a packet, different from Tcp!!!
                if(data.equals("bye"))
                    break;
            }catch (Exception e)
            {
                System.out.println(e.getStackTrace());
            }
        }
        socket.close();//Close
    }
}

//Receive Method Implementation Class
package main.UdpChat;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class ReceiveMessage implements Runnable {
    public int port;//Own Port
    public DatagramSocket socket = null;
    public String who;//Who sent it to me?

    public ReceiveMessage(int port,String who) {
        this.port = port;
        this.who = who;
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true)
        {
            try {
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length);//Pack
                socket.receive(packet);//receive data

                byte[] data = packet.getData();
                String receivedata = new String(data,0,data.length);
                System.out.println(who + " :" +receivedata);//print data
                if(receivedata.equals("bye"))
                    break;
            }catch (Exception e)
            {
                System.out.println(e.getStackTrace());
            }
        }
        socket.close();
    }
}

Now that we've created the method classes, we're going to set up users to use the run methods in these two classes

//Create User A
package main.UdpChat;

public class AChat {
    public static void main(String[] args) {
        //Create a new thread to execute when the cpu has free time
        //New send function, port 7777, port 8888 to localhost
        new Thread(new SendMessage(7777,8888,"localhost")).start();
        //Create a new listen-receive function to listen for information from port 9999 and identify the port as the place where B is connected.
        new Thread(new ReceiveMessage(9999,"B")).start();
    }
}

//Create User B
package main.UdpChat;

public class BChat {
    public static void main(String[] args) {
        //Same as A. My own port is 5555, sent to 9999 localhost
        new Thread(new SendMessage(5555,9999,"localhost")).start();
        //Listen for information from port 8888 and confirm that port is connected to A
        new Thread(new ReceiveMessage(8888,"A")).start();
    }

}

3.2. Implementing effect of UDP

Start AChat and BChat:

Two small green dots light up to indicate the start is complete.

Effect:

That's how UDP is implemented. The main idea comes from the theory of madness!

3.2. Implementing effect of UDP

Start AChat and BChat:

[External chain picture transfer failed, source station may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-wd25LbZV-1634145311514)(C:/Users/13931/Desktop/%E5%AE%9E%E7%94%A8txt/resources/image-20211014004418255.png)]

Two small green dots light up to indicate the start is complete.

Effect:

[External chain picture transfer failed, source station may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-5g 83sofc-1634145311545) (C:/Users/13931/Desktop/%E5%AE%9E%E7%94%A8txt/resources/image-202110004537383.png)]

[External chain picture transfer failed, source station may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-0WqlqX04-1634145311547)(C:/Users/13931/Desktop/%E5%AE%9E%E7%94%A8txt/resources/image-20211014004550065.png)]

That's how UDP is implemented. The main idea comes from the theory of madness!

3.3. Implementation of TCP

  • Consistent implementation first, multithreading is still used, with both receive and send enabled. The main difference between the two is in the construction method. Since UDP is sent and received through a package, no line breaks need to be added, but TCP requires
  • Secondly, to improve performance, we use the implementation subclass of the BufferedReader class because the length of the array cannot be fixed or fixed.
  • The TCP accept method is blocked and waits for a connection when it cannot be received. See the code first if you don't understand this sentence.
//Send Method Implementation Class
package main.Tcp;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class SendMsg implements Runnable{
    private String toIp;//Address to send
    private int toPort;//Port to Send
    private Socket socket;//Sender
    private OutputStream os;//io Flow

    public SendMsg(String toIp, int toPort) {
        this.toIp = toIp;
        this.toPort = toPort;

        try {
            socket = new Socket(toIp,toPort);
            os = socket.getOutputStream();
            os.write("Connection Successful\n".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true)
        {
            try {
                Scanner sc = new Scanner(System.in);
                String data = sc.nextLine() + "\n";//Keyboard input, blocking, you must add a line break here, or the receiver cannot write out of the cache because it uses the BufferedReader class.
                if(data.equals("bye"))//If bye is entered, disconnect.
                    break;
                os.write(data.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            os.close();
            socket.close();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}

//Method Implementation Class for Receive Receiver
package main.Tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Receive implements Runnable {
    private int port;//Current Port
    private String from;//Where do you come from?
    private ServerSocket serverSocket;//Server
    private Socket socket;//Clients received from the server
    private BufferedReader br;//flow

    public Receive(int port, String from) {
        this.port = port;
        this.from = from;
        try {
            serverSocket = new ServerSocket(port);
            socket = serverSocket.accept();
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void run() {
        String data = null;
        while (true) {
            try {
                data = br.readLine();//Read out the data in the buffer stream and note!!! Because ReadLine is used here, writing to the cache is stopped only when line breaks or terminators are encountered, so we add line breaks at the end of every sentence at the sender.
                System.out.println(from +" :" + data);
                if(data == "bye")
                    break;
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        try {
            socket.close();
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

//User A
package main.Tcp;

public class A {
    public static void main(String[] args) {
        //Be aware of the start method
        //Listen for information from 8888, User B
        new Thread(new Receive(8888,"user B")).start();
        //Send information to port 9999 via localhost
        new Thread(new SendMsg("localhost",9999)).start();
    }
}

//User B
package main.Tcp;

import java.util.TreeMap;

public class B {
    public static void main(String[] args) {
        new Thread(new SendMsg("127.0.0.1",8888)).start();
        new Thread(new Receive(9999,"user A")).start();

    }
}

3.4. Implementation results of TCP

Initialization

results of enforcement


This is the implementation of TCP

4. Summary

  • Points of Attention
  1. Use BufferedReader.readline();Write only when line breaks are read.
  2. The port name must match.

Posted by Hisakata on Wed, 13 Oct 2021 10:02:32 -0700