用Tcp实现一对多聊天

1 篇文章 0 订阅
1 篇文章 0 订阅

首先,我们先在idea中用GUI Form设计一个聊天框,swing本人也不是很会,但查看一下GUI Form然后用它来做个界面问题不大。

用idea创建java项目就不写了

在设置和新项目设置中配置和引入依赖

<dependency>
    <groupId>com.intellij</groupId>
    <artifactId>forms_rt</artifactId>
    <version>7.0.3</version>
</dependency>

创建GUI窗体

通过拖动组件实现如下效果

 改变一下拖入的组件字体大小和名字

改变一下textField和两个button的高度,和给这个三个组件添加侦听器

组件中的内容在这里修改

 

 给textArea设置不可编辑

窗口界面就设计结束了,查看代码,可以看到对于的组件和监听方法已加入

alt + insert 在类中生成窗体main方法

修改下代码,实现我们想要的聊天框效果并运行main方法,代码简单就不描述,疑惑的有注释。

package lcj.example;

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

public class ChatServerGUI {
    private JTextArea textArea;
    private JPanel panel;
    private JTextField textField;
    private JButton sendButton;
    private JButton clearButton;

    public ChatServerGUI() {
        textField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textArea.append(textField.getText() + "\n");
                textField.setText("");
            }
        });
        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textArea.append(textField.getText() + "\n");
                textField.setText("");
            }
        });
        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textField.setText("");
            }
        });
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("ChatServerGUI");
        frame.setContentPane(new ChatServerGUI().panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(960, 660);
        frame.setVisible(true);
    }
}

可以看到自动在类中为我们自动生成了窗口设计的代码 

窗体效果

下面开始用tcp实现一对多聊天并通过他来为我们提供界面操作

修改ChatServerGUI类的代码

package lcj.example;

import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import lombok.extern.log4j.Log4j2;

import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.text.StyleContext;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Locale;

@Log4j2
public class ChatServerGUI {
    private JTextArea textArea;
    private JPanel panel;
    private JTextField textField;
    private JButton sendButton;
    private JButton clearButton;

    public ChatServerGUI(int port) {
        JFrame frame = new JFrame("聊天服务器");
        frame.setContentPane(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(960, 660);
        frame.setVisible(true);
        textField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String input = textField.getText();
                textField.setText("");
                textArea.append("服务器:" + input + "\n");
                BufferedWriter bw;
                try {
                    for (Socket socket : clientSocketlist) {
                        bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                        bw.write("服务器:" + input + "\n");
                        bw.flush();
                    }
                } catch (IOException ex) {
                    log.error("", ex);
                }
            }
        });
        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String input = textField.getText();
                textField.setText("");
                textArea.append("服务器:" + input + "\n");
                BufferedWriter bw;
                try {
                    for (Socket socket : clientSocketlist) {
                        bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                        bw.write("服务器:" + input + "\n");
                        bw.flush();
                    }
                } catch (IOException ex) {
                    log.error("", ex);
                }
            }
        });
        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textField.setText("");
            }
        });
        newServerSocket(port);
    }

    private Socket clientSocket;
    private ArrayList<Socket> clientSocketlist = new ArrayList<>();

    public void newServerSocket(int port) {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                clientSocket = serverSocket.accept();
                clientSocketlist.add(clientSocket);
                new Thread(new ClientThread(clientSocket)).start();
            }
        } catch (IOException e) {
            log.error("建立服务器套接字异常:" + e);
        }
    }

    class ClientThread implements Runnable {
        private Socket clientSocket;
        private BufferedReader br;
        String msg;

        ClientThread(Socket socket) {
            this.clientSocket = socket;
            try {
                br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            } catch (IOException e) {
                log.error("", e);
            }
        }

        @Override
        public void run() {
            try {
                while (true) {
                    msg = br.readLine();
                    textArea.append(msg + "\n");
                    for (Socket socket : clientSocketlist) {
                        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                        bw.write(msg + "\n");
                        bw.flush();
                    }
                }
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }

    public static void main(String[] args) {
        new ChatServerGUI(8083);
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        panel = new JPanel();
        panel.setLayout(new GridLayoutManager(2, 3, new Insets(0, 0, 0, 0), -1, -1));
        textArea = new JTextArea();
        textArea.setEditable(false);
        Font textAreaFont = this.$$$getFont$$$(null, -1, 22, textArea.getFont());
        if (textAreaFont != null) textArea.setFont(textAreaFont);
        panel.add(textArea, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false));
        textField = new JTextField();
        Font textFieldFont = this.$$$getFont$$$(null, -1, 22, textField.getFont());
        if (textFieldFont != null) textField.setFont(textFieldFont);
        panel.add(textField, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, 50), null, 0, false));
        sendButton = new JButton();
        Font sendButtonFont = this.$$$getFont$$$(null, -1, 22, sendButton.getFont());
        if (sendButtonFont != null) sendButton.setFont(sendButtonFont);
        sendButton.setText("发送");
        panel.add(sendButton, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 50), null, 0, false));
        clearButton = new JButton();
        Font clearButtonFont = this.$$$getFont$$$(null, -1, 22, clearButton.getFont());
        if (clearButtonFont != null) clearButton.setFont(clearButtonFont);
        clearButton.setText("清空");
        panel.add(clearButton, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 50), null, 0, false));
    }

    /**
     * @noinspection ALL
     */
    private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
        if (currentFont == null) return null;
        String resultName;
        if (fontName == null) {
            resultName = currentFont.getName();
        } else {
            Font testFont = new Font(fontName, Font.PLAIN, 10);
            if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
                resultName = fontName;
            } else {
                resultName = currentFont.getName();
            }
        }
        Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
        boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac");
        Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize());
        return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return panel;
    }

}
package lcj.example;

import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import lombok.extern.log4j.Log4j2;

import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.text.StyleContext;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
import java.util.Locale;

@Log4j2
public class ChatClientGUI {
    private JTextArea textArea;
    private JPanel panel;
    private JTextField textField;
    private JButton sendButton;
    private JButton clearButton;

    private String ip;
    private int port;
    private String userName;

    public ChatClientGUI(String ip, int port, String userName) {
        this.ip = ip;
        this.port = port;
        this.userName = userName;
        createChatGUI();
        newClientSocket();
    }

    public void createChatGUI() {
        JFrame frame = new JFrame(userName);
        frame.setContentPane(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(960, 660);
        frame.setVisible(true);
        textField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String input = textField.getText();
                textField.setText("");
                try {
                    bw.write(userName + ":" + input + "\n");
                    bw.flush();
                } catch (IOException ex) {
                    log.error("", ex);
                }
            }
        });
        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String input = textField.getText();
                textField.setText("");
                try {
                    bw.write(userName + ":" + input + "\n");
                    bw.flush();
                } catch (IOException ex) {
                    log.error("", ex);
                }
            }
        });
        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textField.setText("");
            }
        });
    }

    private BufferedWriter bw;

    public void newClientSocket() {
        try {
            Socket clientSocket = new Socket(ip, port);
            bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            new Thread(new ServerThread(clientSocket)).start();
        } catch (IOException e) {
            log.error("建立套接字连接异常:" + e);
        }
    }

    class ServerThread implements Runnable {
        private Socket clientSocket;
        private BufferedReader br;
        String msg;

        ServerThread(Socket socket) {
            this.clientSocket = socket;
            try {
                br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            } catch (IOException e) {
                log.error("", e);
            }
        }

        @Override
        public void run() {
            try {
                while (true) {
                    msg = br.readLine();
                    textArea.append(msg + "\n");
                }
            } catch (IOException e) {
                log.error("", e);
            }
        }
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        panel = new JPanel();
        panel.setLayout(new GridLayoutManager(2, 3, new Insets(0, 0, 0, 0), -1, -1));
        textArea = new JTextArea();
        textArea.setEditable(false);
        Font textAreaFont = this.$$$getFont$$$(null, -1, 22, textArea.getFont());
        if (textAreaFont != null) textArea.setFont(textAreaFont);
        panel.add(textArea, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false));
        textField = new JTextField();
        Font textFieldFont = this.$$$getFont$$$(null, -1, 22, textField.getFont());
        if (textFieldFont != null) textField.setFont(textFieldFont);
        panel.add(textField, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, 50), null, 0, false));
        sendButton = new JButton();
        Font sendButtonFont = this.$$$getFont$$$(null, -1, 22, sendButton.getFont());
        if (sendButtonFont != null) sendButton.setFont(sendButtonFont);
        sendButton.setText("发送");
        panel.add(sendButton, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 50), null, 0, false));
        clearButton = new JButton();
        Font clearButtonFont = this.$$$getFont$$$(null, -1, 22, clearButton.getFont());
        if (clearButtonFont != null) clearButton.setFont(clearButtonFont);
        clearButton.setText("清空");
        panel.add(clearButton, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 50), null, 0, false));
    }

    /**
     * @noinspection ALL
     */
    private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
        if (currentFont == null) return null;
        String resultName;
        if (fontName == null) {
            resultName = currentFont.getName();
        } else {
            Font testFont = new Font(fontName, Font.PLAIN, 10);
            if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
                resultName = fontName;
            } else {
                resultName = currentFont.getName();
            }
        }
        Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
        boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac");
        Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize());
        return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return panel;
    }
}
package lcj.example;

public class UserA {

    public static void main(String[] args) {
        new ChatClientGUI(("127.0.0.1"), 8083, "用户A");
    }
}

package lcj.example;

public class UserB {

    public static void main(String[] args) {
        new ChatClientGUI(("127.0.0.1"), 8083, "用户B");
    }
}

pom.xml 

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>lcj.example</groupId>
    <artifactId>tcpchat1-n</artifactId>
    <version>1.0</version>

    <name>tcpchat1-n</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.intellij</groupId>
            <artifactId>forms_rt</artifactId>
            <version>7.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.17.2</version>
        </dependency>
    </dependencies>
</project>

src/main/resources/log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO">
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <RollingFile name="RollingFile" fileName="logs/app.log"
                     filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <SizeBasedTriggeringPolicy size="5 MB"/>
        </RollingFile>

        <RollingFile name="SUCCESS_FILE" fileName="logs/success.log"
                     filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <SizeBasedTriggeringPolicy size="5 MB"/>
        </RollingFile>
    </appenders>
    <loggers>
        <root level="DEBUG">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFile"/>
        </root>

        <logger name="success" additivity="false">
            <appender-ref ref="SUCCESS_FILE"/>
        </logger>
    </loggers>
</configuration>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现Java TCP的一对一聊天,可以按照以下步骤进行: 1. 创建一个ServerSocket来监听客户端的连接请求: ```java ServerSocket serverSocket = new ServerSocket(port); Socket clientSocket = serverSocket.accept(); ``` 2. 在客户端中创建一个Socket来连接服务器: ```java Socket socket = new Socket(serverHost, serverPort); ``` 3. 在服务器和客户端中都创建一个输入输出流,用于发送和接收消息: ```java // 服务器端 InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream(); // 客户端 InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); ``` 4. 使用输入输出流进行消息的发送和接收: ```java // 服务器端 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter writer = new PrintWriter(outputStream, true); String message = reader.readLine(); // 读取客户端发送的消息 writer.println("Server received your message: " + message); // 发送回复消息给客户端 // 客户端 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter writer = new PrintWriter(outputStream, true); writer.println("Hello, server!"); // 发送消息给服务器 String response = reader.readLine(); // 读取服务器回复的消息 ``` 5. 在服务器和客户端中都需要使用多线程来处理多个连接请求,否则会阻塞主线程。 完整的示例代码如下: 服务器端: ```java import java.io.*; import java.net.*; public class Server { public static void main(String[] args) throws IOException { int port = 8888; ServerSocket serverSocket = new ServerSocket(port); System.out.println("Server started on port " + port); while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress()); new Thread(() -> { try { InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter writer = new PrintWriter(outputStream, true); while (true) { String message = reader.readLine(); if (message == null) { break; } System.out.println("Received message from client: " + message); writer.println("Server received your message: " + message); } clientSocket.close(); System.out.println("Client disconnected: " + clientSocket.getInetAddress().getHostAddress()); } catch (IOException e) { e.printStackTrace(); } }).start(); } } } ``` 客户端: ```java import java.io.*; import java.net.*; public class Client { public static void main(String[] args) throws IOException { String serverHost = "localhost"; int serverPort = 8888; Socket socket = new Socket(serverHost, serverPort); System.out.println("Connected to server: " + socket.getInetAddress().getHostAddress()); InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter writer = new PrintWriter(outputStream, true); writer.println("Hello, server!"); String response = reader.readLine(); System.out.println("Received response from server: " + response); socket.close(); System.out.println("Disconnected from server."); } } ``` 以上代码可以实现在本地进行一对一的聊天。如果要在不同的机器上进行聊天,需要将服务器端的IP地址替换为服务器的公网IP地址,并且需要在服务器端的防火墙中开放对应的端口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值