[Networking Experiment: Socket Communication Programming TCP/UDP]

Networking Experiment 2: Socket Communication Programming TCP/UDP (Java)

The code below also designs a simple login interface and message sending interface.

TCP

The main steps of Socket programming client

1. Create a Socket instance and specify the connected server Socket address and port number.
2. Obtain the input and output streams through the Socket instance, and use the input and output streams for data transmission.
3. After the communication is completed, close the Socket connection.

The main steps of Socket programming server side

1. Create a server Socket instance and specify the listening port number
2. Start the server Socket and wait for the connection request from the client Socket.
3. After establishing the Socket connection, perform data transmission through the Socket instance.
4. After the communication is completed, close the Socket connection

Server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Server {
    private static Map<String, PrintWriter> clients = new HashMap<>();
    private static Map<String, String> users = new HashMap<>();

    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(12345)) {
            System.out.println("The server has been started, waiting for client connection...");

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connection successful");

                ClientHandler clientHandler = new ClientHandler(clientSocket);
                Thread thread = new Thread(clientHandler);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class ClientHandler implements Runnable {
        private Socket clientSocket;
        private PrintWriter out;
        private BufferedReader in;
        private String username;
        private long loginTime;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        public void run() {
            try {
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                out = new PrintWriter(clientSocket.getOutputStream(), true);

                //Read username and password
                username = in.readLine();
                String password = in.readLine();

                if (isValidUser(username, password)) {
                    loginTime = System.currentTimeMillis();
                    System.out.println("User " + username + " Login successful" + "! Login time: " + getFormattedTime(loginTime));
                    out.println("Login successful, welcome " + username + "! Login time: " + getFormattedTime(loginTime));

                    //Add client to client list
                    synchronized (clients) {
                        clients.put(username, out);
                    }

                    //Receive and broadcast messages
                    String message;
                    while ((message = in.readLine()) != null) {
                        System.out.println(username + ": " + message);
                        broadcastMessage(username + ": " + message);
                    }
                } else {
                    System.out.println("User " + username + " Login failed");
                    out.println("Login failed, please check username and password");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    // Remove the client and close the connection
                    synchronized (clients) {
                        clients.remove(username);
                    }
                    clientSocket.close();
                    System.out.println("User " + username + " has exited");
                    broadcastMessage("User " + username + " has exited");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private static boolean isValidUser(String username, String password) {
            users.put("bu", "21121157");
            users.put("user", "12345");
            return users.containsKey(username) & amp; & amp; users.get(username).equals(password);
        }

        private void broadcastMessage(String message) {
            //Broadcast message to all clients
            synchronized (clients) {
                for (PrintWriter clientWriter : clients.values()) {
                    clientWriter.println(message);
                }
            }
        }

        private String getFormattedTime(long time) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = new Date(time);
            return sdf.format(date);
        }
    }
}

client:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;

public class Client {
    private static Socket socket;
    private static BufferedReader in;
    private static PrintWriter out;
    private static String username;

    private JFrame frame;
    private JTextField usernameField;
    private JPasswordField passwordField;
    private JButton loginButton;
    private JButton exitButton;

    private JTextField messageField;
    private JButton sendButton;
    private JButton sendFileButton;
    private JTextArea chatArea;

    public Client() {
        initialize();
        connectToServer();
    }

    private void initialize() {
        frame = new JFrame("Chat App");
        frame.setPreferredSize(new Dimension(800, 600));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel loginPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(10, 10, 10, 10);

        usernameField = new JTextField(20);
        passwordField = new JPasswordField(20);
        loginButton = new JButton("Login");
        exitButton = new JButton("Exit");

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.insets = new Insets(20, 10, 20, 10);
        loginPanel.add(new JLabel("Welcome to the chat application"), gbc);

        gbc.gridwidth = 1;
        gbc.gridy + + ;
        gbc.anchor = GridBagConstraints.EAST;
        loginPanel.add(new JLabel("Username:"), gbc);
        gbc.gridy + + ;
        loginPanel.add(new JLabel("Password:"), gbc);
        gbc.gridx + + ;
        gbc.gridy--;
        gbc.anchor = GridBagConstraints.WEST;
        loginPanel.add(usernameField, gbc);
        gbc.gridy + + ;
        loginPanel.add(passwordField, gbc);
        gbc.gridx = 0;
        gbc.gridy + + ;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        loginPanel.add(loginButton, gbc);
        gbc.gridy + + ;
        loginPanel.add(exitButton, gbc);

        frame.add(loginPanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        loginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                login();
            }
        });

        exitButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                exit();
            }
        });
    }

    private void connectToServer() {
        try {
            socket = new Socket("localhost", 12345);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void login() {
        username = usernameField.getText();
        String password = new String(passwordField.getPassword());
        out.println(username);
        out.println(password);

        try {
            String serverResponse = in.readLine();
            if (serverResponse.startsWith("Login successful")) {
                frame.getContentPane().removeAll();
                frame.setLayout(new BorderLayout());

                chatArea = new JTextArea();
                chatArea.setEditable(false);
                chatArea.setLineWrap(true);
                JScrollPane scrollPane = new JScrollPane(chatArea);
                frame.add(scrollPane, BorderLayout.CENTER);

                JPanel inputPanel = new JPanel(new BorderLayout());
                frame.add(inputPanel, BorderLayout.SOUTH);

                messageField = new JTextField();
                inputPanel.add(messageField, BorderLayout.CENTER);

                sendButton = new JButton("Send message");
                sendButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        sendMessage();
                    }
                });
                inputPanel.add(sendButton, BorderLayout.EAST);

                sendFileButton = new JButton("Send file");
                sendFileButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        sendFile();
                    }
                });
                inputPanel.add(sendFileButton, BorderLayout.WEST);

                JButton exitChatButton = new JButton("Exit");
                exitChatButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        exit();
                    }
                });
                inputPanel.add(exitChatButton, BorderLayout.SOUTH);

                frame.pack();
                frame.setSize(800, 600);
                frame.revalidate();
                frame.repaint();

                displayMessage(serverResponse);
            } else {
                JOptionPane.showMessageDialog(frame, serverResponse, "Login failed", JOptionPane.ERROR_MESSAGE);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void exit() {
        try {
            socket.close();
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendMessage() {
        String message = messageField.getText();
        if (!message.isEmpty()) {
            out.println(username + ": " + message);
            messageField.setText("");
            displayMessage(username + ": " + message);
        }
    }

    private void sendFile() {
        JFileChooser fileChooser = new JFileChooser();
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            try {
                BufferedReader fileReader = new BufferedReader(new FileReader(selectedFile));
                String fileLine;
                while ((fileLine = fileReader.readLine()) != null) {
                    out.println(fileLine);
                }
                fileReader.close();
                displayMessage("File sent: " + selectedFile.getName());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void displayMessage(String message) {
        chatArea.append(message + "\
");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Client();
            }
        });
    }
}

UDP

Server

import java.io.IOException;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ServerU {
    private static Map<String, InetAddress> clients = new HashMap<>();
    private static Map<String, String> users = new HashMap<>();

    public static void main(String[] args) {
        DatagramSocket socket = null;

        try {
            socket = new DatagramSocket(12345);
            byte[] receiveData = new byte[1024];

            System.out.println("The server has been started, waiting for client connection...");

            while (true) {
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                socket.receive(receivePacket);

                InetAddress clientAddress = receivePacket.getAddress();
                int clientPort = receivePacket.getPort();
                String message = new String(receivePacket.getData(), 0, receivePacket.getLength());

                if (message.startsWith("LOGIN:")) {
                    String[] loginInfo = message.split(":");
                    if (loginInfo.length == 3) {
                        String username = loginInfo[1];
                        String password = loginInfo[2];

                        if (isValidUser(username, password)) {
                            long loginTime = System.currentTimeMillis();
                            System.out.println("User " + username + " Login successful" + "! Login time: " + getFormattedTime(loginTime));
                            sendMessage("Login successful, welcome " + username + "! Login time: " + getFormattedTime(loginTime), clientAddress, clientPort);

                            //Add client to client list
                            synchronized (clients) {
                                clients.put(username, clientAddress);
                            }
                        } else {
                            System.out.println("User " + username + " Login failed");
                            sendMessage("Login failed, please check username and password", clientAddress, clientPort);
                        }
                    }
                } else if (message.startsWith("MSG:")) {
                    String[] msgInfo = message.split(":");
                    if (msgInfo.length == 3) {
                        String username = msgInfo[1];
                        String msg = msgInfo[2];
                        String formattedMessage = username + ": " + msg;

                        //Receive and broadcast messages
                        System.out.println(formattedMessage);
                        broadcastMessage(formattedMessage, username);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null & amp; & amp; !socket.isClosed()) {
                socket.close();
            }
        }
    }

     // Here we simply design a user verification and create two user information
    private static boolean isValidUser(String username, String password) {
        users.put("bu", "211211");
        users.put("user", "12345");
        return users.containsKey(username) & amp; & amp; users.get(username).equals(password);
    }

    private static void sendMessage(String message, InetAddress address, int port) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        byte[] sendData = message.getBytes();
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port);
        socket.send(sendPacket);
        socket.close();
    }

    private static void broadcastMessage(String message, String senderUsername) throws IOException {
        //Broadcast message to all clients
        synchronized (clients) {
            for (Map.Entry<String, InetAddress> entry : clients.entrySet()) {
                if (!entry.getKey().equals(senderUsername)) {
                    sendMessage(message, entry.getValue(), 12345);
                }
            }
        }
    }

    private static String getFormattedTime(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(time);
        return sdf.format(date);
    }
}

Client

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;

public class ClientU {
    private static DatagramSocket socket;
    private static InetAddress serverAddress;
    private static int serverPort = 12345;
    private static String username;

    private JFrame frame;
    private JTextField usernameField;
    private JPasswordField passwordField;
    private JButton loginButton;
    private JButton exitButton;

    private JTextField messageField;
    private JButton sendButton;
    private JButton sendFileButton;
    private JTextArea chatArea;

    public ClientU() {
        initialize();
        connectToServer();
    }

    private void initialize() {
        frame = new JFrame("Chat App");
        frame.setPreferredSize(new Dimension(800, 600));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel loginPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(10, 10, 10, 10);

        usernameField = new JTextField(20);
        passwordField = new JPasswordField(20);
        loginButton = new JButton("Login");
        exitButton = new JButton("Exit");

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.insets = new Insets(20, 10, 20, 10);
        loginPanel.add(new JLabel("Welcome"), gbc);

        gbc.gridwidth = 1;
        gbc.gridy + + ;
        gbc.anchor = GridBagConstraints.EAST;
        loginPanel.add(new JLabel("Username:"), gbc);
        gbc.gridy + + ;
        loginPanel.add(new JLabel("Password:"), gbc);
        gbc.gridx + + ;
        gbc.gridy--;
        gbc.anchor = GridBagConstraints.WEST;
        loginPanel.add(usernameField, gbc);
        gbc.gridy + + ;
        loginPanel.add(passwordField, gbc);
        gbc.gridx = 0;
        gbc.gridy + + ;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        loginPanel.add(loginButton, gbc);
        gbc.gridy + + ;
        loginPanel.add(exitButton, gbc);

        frame.add(loginPanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        loginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                login();
            }
        });

        exitButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                exit();
            }
        });
    }

    private void connectToServer() {
        try {
            socket = new DatagramSocket();
            serverAddress = InetAddress.getByName("localhost");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void login() {
        username = usernameField.getText();
        String password = new String(passwordField.getPassword());

        String loginMessage = "LOGIN:" + username + ":" + password;
        sendUDPMessage(loginMessage);

        try {
            byte[] receiveData = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            socket.receive(receivePacket);

            String serverResponse = new String(receivePacket.getData(), 0, receivePacket.getLength());
            if (serverResponse.startsWith("Login successful")) {
                frame.getContentPane().removeAll();
                frame.setLayout(new BorderLayout());

                chatArea = new JTextArea();
                chatArea.setEditable(false);
                chatArea.setLineWrap(true);
                JScrollPane scrollPane = new JScrollPane(chatArea);
                frame.add(scrollPane, BorderLayout.CENTER);

                JPanel inputPanel = new JPanel(new BorderLayout());
                frame.add(inputPanel, BorderLayout.SOUTH);

                messageField = new JTextField();
                inputPanel.add(messageField, BorderLayout.CENTER);

                sendButton = new JButton("Send message");
                sendButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        sendMessage();
                    }
                });
                inputPanel.add(sendButton, BorderLayout.EAST);

                sendFileButton = new JButton("Send file");
                sendFileButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        sendFile();
                    }
                });
                inputPanel.add(sendFileButton, BorderLayout.WEST);

                JButton exitChatButton = new JButton("Exit");
                exitChatButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        exit();
                    }
                });
                inputPanel.add(exitChatButton, BorderLayout.SOUTH);

                frame.pack();
                frame.setSize(800, 600);
                frame.revalidate();
                frame.repaint();

                displayMessage(serverResponse);
            } else {
                JOptionPane.showMessageDialog(frame, serverResponse, "Login failed", JOptionPane.ERROR_MESSAGE);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void exit() {
        socket.close();
        System.exit(0);
    }

    private void sendMessage() {
        String message = messageField.getText();
        if (!message.isEmpty()) {
            String chatMessage = "MSG:" + username + ":" + message;
            sendUDPMessage(chatMessage);
            messageField.setText("");
            displayMessage(username + ": " + message);
        }
    }

    private void sendFile() {
        JFileChooser fileChooser = new JFileChooser();
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            try {
                BufferedReader fileReader = new BufferedReader(new FileReader(selectedFile));
                String fileLine;
                while ((fileLine = fileReader.readLine()) != null) {
                    String fileMessage = "MSG:" + username + ":" + fileLine;
                    sendUDPMessage(fileMessage);
                }
                fileReader.close();
                displayMessage("File sent: " + selectedFile.getName());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void displayMessage(String message) {
        chatArea.append(message + "\
");
    }

    private void sendUDPMessage(String message) {
        try {
            byte[] sendData = message.getBytes();
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverAddress, serverPort);
            socket.send(sendPacket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ClientU();
            }
        });
    }
}

Capitalize the string sent from the client to the server and echo it to the client.

Server:
import java.net.*;
import java.util.Arrays;

public class UDPServer {
    public static void main(String[] args) {
        DatagramSocket socket = null;

        try {
            socket = new DatagramSocket(12345);

            while (true) {
                byte[] receiveData = new byte[1024];
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);

                socket.receive(receivePacket);

                InetAddress clientAddress = receivePacket.getAddress();
                int clientPort = receivePacket.getPort();

                String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());

                //Convert string to uppercase
                String uppercaseMessage = receivedMessage.toUpperCase();

                byte[] sendData = uppercaseMessage.getBytes();
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, clientAddress, clientPort);

                socket.send(sendPacket);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (socket != null & amp; & amp; !socket.isClosed()) {
                socket.close();
            }
        }
    }
}

Client:
import java.net.*;
import java.util.Scanner;

public class UDPClient {
    public static void main(String[] args) {
        DatagramSocket socket = null;

        try {
            socket = new DatagramSocket();

            InetAddress serverAddress = InetAddress.getByName("localhost");
            int serverPort = 12345;

            Scanner scanner = new Scanner(System.in);

            while (true) {
                System.out.print("Enter message (or enter 'exit' to exit): ");
                String message = scanner.nextLine();

                if (message.equals("exit")) {
                    break;
                }

                byte[] sendData = message.getBytes();
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverAddress, serverPort);

                socket.send(sendPacket);

                byte[] receiveData = new byte[1024];
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);

                socket.receive(receivePacket);

                String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
                System.out.println("Server response: " + receivedMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (socket != null & amp; & amp; !socket.isClosed()) {
                socket.close();
            }
        }
    }
}

The main differences and characteristics of TCP and UDP programming.

Connection establishment and termination:
TCP: TCP is a connection-oriented protocol. Before data can be transferred, it needs to establish a connection through a “three-way handshake” process. After the data transfer is completed, the connection needs to be terminated through the “four wave” process.
UDP: UDP is a connectionless protocol. There is no need to establish a connection before sending data, and there is no need to terminate the connection.
data transmission:
TCP: TCP provides reliable data transmission. It uses mechanisms such as acknowledgments, timeouts, and retransmissions to ensure the order and integrity of data packets.
UDP: UDP does not guarantee the reliability of data transmission. Packets may be lost or arrive in a different order at the receiver.
Data check:
TCP: TCP provides an error checking mechanism that can detect whether data is damaged during transmission.
UDP: UDP has no error checking mechanism.
flow control:
TCP: TCP provides a flow control mechanism that prevents the sender from exceeding the receiver’s processing capabilities.
UDP: UDP has no flow control mechanism.
transfer method:
TCP: TCP is byte stream oriented. It treats data as an unbounded byte stream and does not care about the internal structure of the data.
UDP: UDP is datagram oriented. It preserves data boundaries and each datagram is processed individually.
Header overhead:
TCP: TCP has a larger header overhead than UDP. The TCP header is fixed at 20 bytes, while the UDP header is fixed at 8 bytes.
UDP: UDP has less header overhead and is therefore more suitable for transmitting small packets.
Programming interface:
TCP: TCP uses the socket programming interface, and commonly used programming languages provide support for sockets.
UDP: UDP also uses the socket programming interface, but uses a different socket type (DGRAM socket).
Application scenarios:
TCP: TCP is suitable for data transmission scenarios that require reliable, orderly and error checking, such as web browsing, email, etc.
UDP: UDP is suitable for applications with high real-time requirements, such as video calls, online games, etc., where packet loss or rearrangement has a small impact on the application.

Note: The above code and information are mainly my simple records of the experiment. If you don’t know how to run it, I use eclipse. When using it, you can open two IDEs, one to run the Server and one to run the Client. .