13.Java实现P2P聊天软件(客户端代码)

上一篇实现了服务端,本篇主要展示 客户端代码的设计
客户端的代码比较复杂一点,由于P2P中,客户端要二者兼顾。
注意:目前本实例中只实现了消息的传输,但大致框架已定,后面的文件传输很简单了。

废话不多,首先上效果:(由于时间比较紧,只是初步实现了,欢迎大家二次创作,优化加强!!)

在这里插入图片描述

项目地址:https://gitee.com/yan-jiadou/study/tree/master/Java%E5%8A%A8%E6%89%8B%E5%81%9A%E4%B8%80%E5%81%9A/src/main/java/InternetCode/Socket/JJTalk

详细代码如下:

JJTalkClient.java
它是客户端主程序

package InternetCode.Socket.JJTalk;

import InternetCode.Socket.JJTalk.ClientUtil.ClientAbleUtil;
import InternetCode.Socket.JJTalk.ClientUtil.ClientThread;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

import static InternetCode.Socket.JJTalk.ClientUtil.ClientAbleUtil.makeActiveClientInfo;

public class JJTalkClient {
    // 创建流对象
    private ObjectOutputStream out = null;
    // 创建流对象
    private ObjectInputStream in = null;
    //声明服务器Socket
    private ServerSocket serverSocket;

    /**
     * 新建服务器对象并等待连接
     */
    public void getConnect(){
        try { // 捕捉异常
            Socket socket;
            System.out.println("开始连接服务器");
            socket = new Socket("127.0.0.1", 2006); // 实例化Socket对象
            //客户端信息注册
            ClientAbleUtil ableUtil=new ClientAbleUtil();
            ableUtil.sendObject(makeActiveClientInfo(),socket);
            new ClientThread(socket,ableUtil,"N","成功连接到服务器").start();
        } catch (Exception e) {
            e.printStackTrace(); // 输出异常信息
        }
    }

    /**
     * 新建服务器对象并等待连接
     */
    public void getServer() {
        try {
            serverSocket = new ServerSocket(1998);
            while (true) {
                Socket socket;
                // 监听是否有客户端连接
                System.out.println("等待连接!!");
                socket = serverSocket.accept();
                System.out.println("连接成功!");
                ClientAbleUtil ableUtil=new ClientAbleUtil();
                // 创建并启动连接线程对象
                ClientThread clientThread=new ClientThread(socket,ableUtil,"Y",socket.getInetAddress().getHostName()+"向您发起会话");
                clientThread.start();
            }
        } catch (Exception e) {
            e.printStackTrace(); // 输出异常信息
        }
    }

    public static void main(String[] args) {
       JJTalkClient client=new JJTalkClient();
       //连接服务器线程
       new Thread(new Runnable() {
           @Override
           public void run() {
               client.getConnect();
           }
       }).start();
       //监听连接线程
       new Thread(new Runnable() {
           @Override
           public void run() {
               client.getServer();
           }
       }).start();
    }

}

ClientThread.java
它主要负责图形化界面的展示和事件处理

package InternetCode.Socket.JJTalk.ClientUtil;

import InternetCode.Socket.JJTalk.pojo.ClientInfo;

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 ClientThread extends Thread{
    //连接服务器的套接字
    Socket socket;
    ClientAbleUtil ableUtil;
    //连接客户端的套接字
    Socket clientSocket;
    ClientAbleUtil ableUtil1;
    //是否客户端标志
    String clientFlat;
    String text;
    // 创建JTextArea对象
    public JTextArea outInfo = new JTextArea();

    public ClientThread(Socket socket,ClientAbleUtil ableUtil,String clientFlat,String text) throws IOException {
        this.socket = socket;
        this.ableUtil=ableUtil;
        this.clientFlat=clientFlat;
        this.text=text;
    }

    public void run() {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //运行图像化界面
                    Frame frame=new Frame(text);
                    frame.setVisible(true);
                }
            }).start();
            //监听发送方发送的消息
            if(clientFlat.equals("Y")){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        while (true){
                            String line=ableUtil.getInfo(socket);
                            if(line!=null){
                                outInfo.append("\n");
                                outInfo.append(socket.getInetAddress().getHostName()+"发送消息:"+line);
                            }
                        }
                    }
                }).start();
            }

        } catch (Exception e) {
            System.out.println(socket + "已经退出。\n");
        }
    }

    class Frame extends JFrame{
        //连接客户端文本框
        private JTextField connectJText;
        //发送信息文本狂
        private JTextField sendInfoJText;

        public Frame(String text) {
            super();
            setTitle("客户端程序");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(500, 100, 800, 700);
            final JScrollPane scrollPane = new JScrollPane();
            getContentPane().setLayout(new GridLayout(1,2));
            getContentPane().add(scrollPane);
            scrollPane.setViewportView(outInfo);
            getContentPane().add(getMainPanel());
            outInfo.append(text);
        }

        /**得到按钮对象
         * @return 按钮对象
         */
        protected JButton getButton(String text) {
            JButton jButton=new JButton();
            jButton = new JButton();
            jButton.addActionListener(new ActionListener() {
                public void actionPerformed(final ActionEvent e) {
                    if(text.equals("连接")){
                        ClientInfo clientInfo=new ClientInfo();
                        clientInfo.setClientId(connectJText.getText());
                        clientInfo.setQuery("Y");
                        System.out.println("开始向服务器发送查询信息");
                        ableUtil.sendObject(clientInfo,socket);
                        //等待接收服务器发送来的客户信息
                        try{
                            clientInfo=ableUtil.getClientInfoFromServer(socket);
                        }catch (Exception e3){
                            e3.printStackTrace();
                        }
                        if(clientInfo.isActive().equals("Y")){
                            //连接通信对方
                            try {
                                outInfo.append("开始连接客户:"+clientInfo.getClientId());
                                // 实例化Socket对象
                                clientSocket = new Socket(clientInfo.getIp(),Integer.parseInt(clientInfo.getPort()));
                                ableUtil1=new ClientAbleUtil();
                                outInfo.append("\n");
                                outInfo.append("连接成功!!可以开始通信了");
                                //监听请求方发送的消息
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        while (true){
                                            String line=ableUtil1.getInfo(clientSocket);
                                            if(line!=null){
                                                outInfo.append("\n");
                                                outInfo.append(clientSocket.getInetAddress().getHostName()+"发送消息:"+line);
                                            }
                                        }
                                    }
                                }).start();
                            } catch (Exception ex) {
                                ex.printStackTrace(); // 输出异常信息
                            }
                        }else if(clientInfo.isActive().equals("N")){
                            //对方不在线,输出提示信息
                            outInfo.append("对方不在线,请稍后在试!!");
                        }else{
                            outInfo.append("不存在此用户!!!请检查");
                        }
                    }
                    //发送消息给对方
                    if(text.equals("发送")){
                        if(clientFlat.equals("N")){
                            ableUtil1.sendInfo(sendInfoJText.getText(),clientSocket);
                        }else{
                            ableUtil.sendInfo(sendInfoJText.getText(),socket);
                        }
                    }

                    if(text.equals("选择文件")){

                    }

                    if(text.equals("发送文件")){

                    }

                }
            });
            jButton.setText(text);

            return jButton;
        }
        /**
         * 得到画板对象
         * @return 返回画板
         */
        protected JPanel getMainPanel() {
            JPanel panel;
            panel = new JPanel();
            panel.setLayout(new GridLayout(4,1));
            panel.add(getConnectPanel());
            panel.add(getSendDataPanel());
            panel.add(getSendDataPathPanel());
            panel.add(getSendInfoPanel());
            return panel;
        }

        /**
         * 得到连接客户端画板对象
         * @return 返回画板
         */
        protected JPanel getConnectPanel() {
            JPanel panel;
            connectJText=getJTextFiled(100,25);
            panel = new JPanel();
            panel.add(getLabel("对方客户端名称:"));
            panel.add(connectJText);
            panel.add(getButton("连接"));
            return panel;
        }

        /**
         * 得到发送信息的画板
         * @return
         */
        protected JPanel getSendInfoPanel() {
            JPanel panel;
            sendInfoJText=getJTextFiled(200,100);
            panel = new JPanel();
            panel.add(getLabel("请输入要发送的信息:"));
            panel.add(sendInfoJText);
            panel.add(getButton("发送"));
            return panel;
        }
        /**
         * 得到发送数据文件的画板
         * @return 发送数据的画板
         */
        protected JPanel getSendDataPanel() {
            JPanel panel;
            panel = new JPanel();
            panel.add(getLabel("选择要发送的文件:"));
            panel.add(getButton("选择文件"));
            return panel;
        }
        /**
         * 得到发送数据文件的画板
         * @return 发送数据的画板
         */
        protected JPanel getSendDataPathPanel() {
            JPanel panel;
            panel = new JPanel();
            panel.add(getLabel("文件路径:"));
            panel.add(getButton("发送文件"));
            return panel;
        }

        /**文本标签
         * @return
         */
        protected JLabel getLabel(String text) {
            JLabel jLabel=new JLabel();
            jLabel.setText(text);
            return jLabel;
        }

        /**获得输入框
         * @param width
         * @param height
         * @return 输入框对象
         */
        protected JTextField getJTextFiled(int width,int height) {
            JTextField jTextField;
            jTextField = new JTextField();
            jTextField.setPreferredSize(new Dimension(width, height));
            return jTextField;
        }

    }

}

ClientAbleUtil.java
这个类主要将Socket通信能力集合起来方便使用

package InternetCode.Socket.JJTalk.ClientUtil;

import InternetCode.Socket.JJTalk.pojo.ClientInfo;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientAbleUtil {

    private ObjectOutputStream objectOut;
    private ObjectInputStream objectIn;
    private PrintWriter infoOut;
    private BufferedReader infoIn;
    private DataOutputStream DataOut;
    private DataInputStream DataIn;


    /**
     * 生成活跃信息
     * @return
     * @throws UnknownHostException
     */
    public static ClientInfo makeActiveClientInfo() throws UnknownHostException {
        InetAddress inetAdder = InetAddress.getLocalHost();
        ClientInfo clientInfo=new ClientInfo();
        clientInfo.setClientId(String.valueOf(System.currentTimeMillis()));
        clientInfo.setActive("Y");
        clientInfo.setIp(inetAdder.getHostAddress());
        clientInfo.setPort("1998");
        clientInfo.setQuery("N");
        return clientInfo;
    }

    /**
     * 发送信息
     * @param info
     * @param socket
     */
    public void sendInfo(String info, Socket socket){
        try{
            if(infoOut==null){
                infoOut=new PrintWriter(socket.getOutputStream(),true);
            }
            infoOut.println(info);
            System.out.println("发送消息完成: "+info+"发送到:"+socket.getInetAddress().getHostAddress()+":"+socket.getPort());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 发送对象
     * @param obj 要发送的对象
     * @param socket 连接套接字
     */
   public void sendObject(Object obj, Socket socket){
        try {
            if(objectOut==null){
                objectOut=new ObjectOutputStream(socket.getOutputStream());
            }
            objectOut.writeObject(obj);
            System.out.println("发送对象完成");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 发送数据文件
     * @param file 要发送的文件对象
     * @param socket 连接套接字
     */
    public void sendData(File file, Socket socket){
        long lengths;
        try {
            if(socket!=null){
                if(DataOut==null){
                    DataOut=new DataOutputStream(socket.getOutputStream());
                }
                DataInputStream inStream = null;// 定义数据输入流对象
                FileInputStream inFile;
                if (file != null) {
                    lengths = file.length();
                    inFile=new FileInputStream(file);
                    inStream = new DataInputStream(inFile);
                } else {
                    System.out.println("没有选择文件。");
                    return;
                }
                DataOut.writeLong(lengths);
                DataOut.writeUTF(file.getName());
                byte[] bt = new byte[(int) lengths];
                int len = -1;
                while ((len = inStream.read(bt)) != -1) {
                    DataOut.write(bt);// 将字节数组写入输出流
                }
                inStream.close();
                inFile.close();
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * 监听接收服务端返回的对象信息
     * @param socket
     * @return
     */
    public ClientInfo getClientInfoFromServer(Socket socket) throws IOException {
        try {
            if(socket!=null){
                if(objectIn==null){
                    objectIn=new ObjectInputStream(socket.getInputStream());
                }
                while (true){
                    ClientInfo clientInfo=(ClientInfo) objectIn.readObject();
                    if(clientInfo!=null){
                        System.out.println("接收对象完成");
                        return clientInfo;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            objectIn.close();
        }
        return null;
    }

    /**
     * 监听其他节点传过来的信息
     * @param socket
     * @return
     */
    public  String getInfo(Socket socket){
        String info=null;
        try {
            if(socket!=null){
                if(infoIn==null){
                    infoIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                }
                while (true){
                    info=infoIn.readLine();
                    if(info!=null){
                        System.out.println("接收消息完成:"+info);
                        return info;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 等待客户端发送数据并接收
     */
    public boolean getData(Socket socket) {
        try {
            if(socket!=null){
                if(DataIn==null){
                    DataIn=new DataInputStream(socket.getInputStream());
                }
                while (true){
                    // 读取数据文件大小
                    long lengths = DataIn.readLong();
                    if(lengths>0){
                        String fileName=DataIn.readUTF();
                        // 创建字节数组
                        byte[] bt = new byte[(int) lengths];
                        for (int i = 0; i < bt.length; i++) {
                            bt[i] = DataIn.readByte();// 读取字节信息并存储到字节数组
                        }
                        File img=new File(String.valueOf(Math.random())+fileName);
                        OutputStream out=new DataOutputStream(new FileOutputStream(img));
                        out.write(bt);
                        System.out.println("文件接收成功!!");
                        return true;
                    }
                }
            }

        } catch(Exception e){
            e.printStackTrace();
        } finally {
            try {
                if (DataIn != null) {
                    DataIn.close();// 关闭流
                }
                if (socket != null) {
                    socket.close(); // 关闭套接字
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
}
  • 10
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
以下是Java实现P2P聊天通信的步骤: 1. 创建一个服务器,用于客户端之间的通信。服务器需要监听客户端的连接请求,并将客户端的信息存储在一个列表中。 2. 创建一个客户端,用于与其他客户端进行通信。客户端需要向服务器注册自己的信息,包括唯一主键、IP地址和端口号。 3. 当客户端想要与其他客户端进行通信时,它需要向服务器查询目标客户端的信息,包括IP地址和端口号。 4. 客户端通过目标客户端的IP地址和端口号连接到目标客户端,建立通信连接。 5. 一旦连接建立成功,客户端之间就可以通过套接字进行通信,发送和接收消息、图片、音频和视频等文件。 以下是Java实现P2P聊天通信的代码示例: 1. 服务器代码 ```java import java.io.*; import java.net.*; import java.util.*; public class Server { private static List<ClientInfo> clients = new ArrayList<ClientInfo>(); public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server started."); while (true) { Socket socket = serverSocket.accept(); System.out.println("New client connected: " + socket.getInetAddress().getHostAddress()); ClientInfo clientInfo = new ClientInfo(socket); clients.add(clientInfo); Thread thread = new Thread(new ServerHandler(clientInfo, clients)); thread.start(); } } catch (IOException e) { e.printStackTrace(); } } } class ServerHandler implements Runnable { private ClientInfo clientInfo; private List<ClientInfo> clients; public ServerHandler(ClientInfo clientInfo, List<ClientInfo> clients) { this.clientInfo = clientInfo; this.clients = clients; } public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(clientInfo.getSocket().getInputStream())); while (true) { String message = reader.readLine(); System.out.println("Received message from " + clientInfo.getId() + ": " + message); if (message.startsWith("REGISTER")) { String[] parts = message.split(" "); clientInfo.setId(parts[1]); clientInfo.setIp(clientInfo.getSocket().getInetAddress().getHostAddress()); clientInfo.setPort(Integer.parseInt(parts[2])); System.out.println("Registered client " + clientInfo.getId() + " at " + clientInfo.getIp() + ":" + clientInfo.getPort()); } else if (message.startsWith("QUERY")) { String[] parts = message.split(" "); String targetId = parts[1]; ClientInfo targetClient = null; for (ClientInfo client : clients) { if (client.getId().equals(targetId)) { targetClient = client; break; } } if (targetClient != null) { String response = "CONNECT " + targetClient.getIp() + " " + targetClient.getPort(); PrintWriter writer = new PrintWriter(clientInfo.getSocket().getOutputStream()); writer.println(response); writer.flush(); System.out.println("Sent response to " + clientInfo.getId() + ": " + response); } else { String response = "ERROR Target client not found."; PrintWriter writer = new PrintWriter(clientInfo.getSocket().getOutputStream()); writer.println(response); writer.flush(); System.out.println("Sent response to " + clientInfo.getId() + ": " + response); } } else { // Forward message to target client String[] parts = message.split(" "); String targetId = parts[0]; ClientInfo targetClient = null; for (ClientInfo client : clients) { if (client.getId().equals(targetId)) { targetClient = client; break; } } if (targetClient != null) { PrintWriter writer = new PrintWriter(targetClient.getSocket().getOutputStream()); writer.println(message); writer.flush(); System.out.println("Forwarded message from " + clientInfo.getId() + " to " + targetClient.getId() + ": " + message); } else { String response = "ERROR Target client not found."; PrintWriter writer = new PrintWriter(clientInfo.getSocket().getOutputStream()); writer.println(response); writer.flush(); System.out.println("Sent response to " + clientInfo.getId() + ": " + response); } } } } catch (IOException e) { e.printStackTrace(); } } } class ClientInfo { private String id; private String ip; private int port; private Socket socket; public ClientInfo(Socket socket) { this.socket = socket; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public Socket getSocket() { return socket; } } ``` 2. 客户端代码 ```java import java.io.*; import java.net.*; public class Client { private static String id; private static String ip; private static int port; public static void main(String[] args) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Enter your ID: "); id = reader.readLine(); Socket socket = new Socket("localhost", 8888); System.out.println("Connected to server."); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println("REGISTER " + id + " 0"); writer.flush(); BufferedReader serverReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String response = serverReader.readLine(); System.out.println("Received response from server: " + response); if (response.startsWith("CONNECT")) { String[] parts = response.split(" "); ip = parts[1]; port = Integer.parseInt(parts[2]); System.out.println("Connected to client " + id + " at " + ip + ":" + port); Thread thread = new Thread(new ClientHandler(socket)); thread.start(); while (true) { String message = reader.readLine(); Socket targetSocket = new Socket(ip, port); PrintWriter targetWriter = new PrintWriter(targetSocket.getOutputStream()); targetWriter.println(id + " " + message); targetWriter.flush(); targetSocket.close(); } } else { System.out.println("Failed to connect to client " + id); } } catch (IOException e) { e.printStackTrace(); } } } class ClientHandler implements Runnable { private Socket socket; public ClientHandler(Socket socket) { this.socket = socket; } public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (true) { String message = reader.readLine(); System.out.println("Received message: " + message); } } catch (IOException e) { e.printStackTrace(); } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小牧之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值