Java实现TCP一对一通信,UDP协议实现群聊

实现服务端对话框:

其中可自行更改对话框大小样式等配置。

package com.ex.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class QqMain extends JFrame implements ActionListener{
    public static void main(String[] args){
 
        InetAddress ia = null;
        try {
            ia = ia.getLocalHost();
            String localip = ia.getHostAddress();
            System.out.println("本机的ip是 :" + localip);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        new QqMain();
    }
 
 
    // 说明:一个类需要页面的显示,则那个类要继承JFrame。
    // 属性
    // 文本域
    private JTextArea jta;
    // 滚动条
    private JScrollPane jsp;
    // 面板里面是文本框和按钮
    private JPanel jp;
    private JTextField jtf;
    private JButton jb ;
 
    BufferedWriter bw  = null;
 
    // 构造器
    public QqMain(){
 
        // 初始化上面的属性
        jta = new JTextArea();
 
        // 将文本域添加到滚动条中
        jsp = new JScrollPane(jta);
        jp = new JPanel();
        jtf =new JTextField(15);
        jb = new JButton("发送");
 
        // 把按钮和文本框添加到面板中
        jp.add(jtf);
        jp.add(jb);
 
        // 把滚动条和面板添加到JFrame中去
        this.add(jsp,BorderLayout.CENTER); //这个设置在中间
        this.add(jp,BorderLayout.SOUTH); //南
 
        this.setTitle("qq聊天");
        this.setSize(500,500);
        this.setLocation(200, 200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
 
        /***********TCP协议*************/
        jb.addActionListener(this);  // 这是按钮点击使用
        // 回车键的监听事件 在接口KeyListener中
        //jtf.addKeyListener(this);
 
 
        jtf.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                if((char)e.getKeyChar()==KeyEvent.VK_ENTER) {
                    useVoid();
                }
            }
        });
 
        try{
            // 1.创建一个服务端的套接字
            ServerSocket serverSocket = new ServerSocket(8888);
 
            //2.等待客户端的连接
            Socket socket = serverSocket.accept();
 
            // 3.获取socket通道的输入流(输入流的读取方式为一行一行的读取方式 ----> readLine())
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 
            // 4.获取通道的输入流(也是一行一行的写出  BufferedWriter ->newLine())
            // 当用户点击“发送”按钮的时候才会,写出数据
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String line = null;
            while((line = br.readLine()) !=null){
                // 将读取的数据拼接到文本域中显示
                jta.append(line + "\n");
            }
 
 
            // 5.关闭socket通道
            serverSocket.close();
 
        }catch(IOException e){
            e.printStackTrace();
        }
 
        /************************/
 
 
    }
    // 点击按钮所实现的方法
    public void actionPerformed(ActionEvent e){
        useVoid();
    }
 
    public void useVoid(){
        // 1.获取文本框中的内容
        String text = jtf.getText();
        text = "服务端对客户端说:" + text;
        // 自己显示
        jta.append(text + "\n");
        // 2.发送
        try{
            // 4.发送
            bw.write(text);
            bw.newLine(); // 换行
            bw.flush();  // 刷新
            // 5.清空文本框
            jtf.setText("");
        }catch (IOException e1){
            e1.printStackTrace();
        }
    }
 
 
	/*public void KeyPressed(KeyEvent e){
		//回车键
		System.out.println("按钮数字");
	}
	public void KeyTyped(KeyEvent e){
	}
	public void KeyReleased(KeyEvent e){
	}*/
    //行为
}

实现客户端的对话框,获取了服务端的ip地址和端口号后进行链接即可。

package com.ex.controller;
 
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class QqFu extends JFrame implements ActionListener{
    public static void main(String[] args){
        new QqFu();
    }
    // 说明:一个类需要页面的显示,则那个类要继承JFrame。
    // 属性
    // 文本域
    private JTextArea jta;
    // 滚动条
    private JScrollPane jsp;
    // 面板里面是文本框和按钮
    private JPanel jp;
    private JTextField jtf;
    private JButton jb ;
 
    BufferedWriter bw = null;
 
    // 构造器
    public QqFu(){
 
        // 初始化上面的属性
        jta = new JTextArea();
 
        // 将文本域添加到滚动条中
        jsp = new JScrollPane(jta);
        jp = new JPanel();
        jtf =new JTextField(15);
        jb = new JButton("发送");
 
        // 把按钮和文本框添加到面板中
        jp.add(jtf);
        jp.add(jb);
 
        // 把滚动条和面板添加到JFrame中去
        this.add(jsp,BorderLayout.CENTER); //这个设置在中间
        this.add(jp,BorderLayout.SOUTH); //南
 
        this.setTitle("qq聊天客户端");  //获取用户的昵称
        this.setSize(500,500);
        this.setLocation(200, 200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        jb.addActionListener(this);
 
        // 回车点击事件
 
        jtf.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                if((char)e.getKeyChar()==KeyEvent.VK_ENTER) {
                    useVoid01();
                }
            }
        });
 
 
 
        try{
            /*******客户端 TCP协议*********/
            // 1.创建一个客户端的套接字(尝试连接)
            Socket socket = new Socket("127.0.0.1",8888);
            // 2.获取socket通道的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 3
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String line = null;
            while((line = br.readLine()) !=null){
                jta.append(line + "\n");
            }
            // 3. 获取输出流
 
            // 4.关闭流
            socket.close();
 
            /******************************/
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public void actionPerformed(ActionEvent e){
        useVoid01();
    }
 
    public void useVoid01(){
        // 1.获取文本框中需要发送的内容
        String text = jtf.getText();
        // 2. 拼接内容
        text = "客户端对服务端说:" + text;
        // 3.自己显示
        jta.append(text + "\n");
        try{
            // 4.发送
            bw.write(text);
            bw.newLine(); // 换行
            bw.flush();  // 刷新
            // 5.清空
            jtf.setText("");
 
        }catch(IOException e1){
            e1.printStackTrace();
        }
    }
    //行为
}

必须先启动服务端再启动客户端才可,如果是两台电脑的情况下,只需要获得其中一个电脑的ip进行服务器启动,另一个进行链接即可。就可实现实时对话

效果展示:

服务器端:
1.1 服务器端继承JFrame框架,添加组件。
1.2 创建服务器端socket。建立一个哈希表,用于存储客户端的昵称以及服务器端对于每个连接的客户端建立的输出流。
1.3建立一个线程池,为每个连接的客户端分配一个执行线程。
1.3调用服务器端Socket的accept()函数,等待客户端的连接,每连接到一个客户端,线程池给相应的客户端分配一个线程。
1.4每个线程内,调用服务器端Socket,封装getOutputStream(),获得服务器端Socket相对应于连接的客户端的输出流和输入流。输入流首先读取到客户端发送来的昵称。将客户端的昵称和服务器端的输出流存储在哈希表中,并遍历整个哈希表,将某人上线的通知发送给所有的在线客户端。
1.5客户端将信息发送给服务器端,当服务器端传来的信息符合“@私聊对象:私聊信息”的格式时,服务器端认为这是私聊信息。服务器端将把私聊对象的昵称从信息中提取出来,通过哈希表找到与昵称对应的输出流。将私聊信息通过输出流发送给私聊对象。
当不是私聊信息时,服务器遍历整个哈希表,通过每个客户端对应的输出流发送给每个客户端。
1.6当客户端下线时,服务器端将移除哈希表中对应存储的客户端昵称以及输出流。并通知在线的每个客户端,某人已下线。

(二) 客户端:
2.1 客户端继承框架JFrame,添加各种组件。
2.2 创建客户端Socket,设置请求连接服务器端IP,以及使用的端口号。
2.3 封装客户端Socket的getInputStream()函数,获得客户端Socket的输入流接受服务器端发来的信息,封装Socket的getOutputStream()函数,获得Socket的输出流向服务器端发送信息。
2.4 通过向文本框添加动作事件监听器,监听文本框的输入。
2.5 当与服务器端连接成功时,系统提醒输入昵称。系统将对输入的昵称进行检索。判断是否有重复的昵称。如有重复则创建不成功,继续输入。
2.6 向服务器端发送信息时,如想对某人发送私聊信息,则需输入符合“@私聊对象的呢称:私聊信息”的格式,此时只有私聊对象和本人可以接收到。否则,发送的信息为公聊信息,所有的客户端都能够收到。
2.7 客户端不断接受服务器端的信息显示在文本域。
1、服务器端:

package server;

import java.io.*;  
import java.net.*;  
import java.util.HashMap;  
import java.util.Map;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ThreadPoolExecutor;  
import javax.swing.*;
import java.awt.*;

public class TCPServer extends JFrame{      

    private JTextArea m_display=new JTextArea();

    private ServerSocket serverSocket;  

    /** 
    * 创建线程池来管理客户端的连接线程 
    * 避免系统资源过度浪费 
    */  
    private ExecutorService exec;  

    // 存放客户端之间私聊的信息  
    private Map<String,PrintWriter> storeInfo;  

    public TCPServer() {  
        super("聊天程序服务器端");
        Container c=getContentPane();
        c.add(new JScrollPane(m_display),BorderLayout.CENTER);
        try {  

            serverSocket = new ServerSocket(6666);  
            storeInfo = new HashMap<String, PrintWriter>();  
            exec = Executors.newCachedThreadPool();  

        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  

    // 将客户端的信息以Map形式存入集合中  
    private void putIn(String key,PrintWriter value) {  
        synchronized(this) {  
            storeInfo.put(key, value);  
        }  
    }  

    // 将给定的输出流从共享集合中删除  
    private synchronized void remove(String  key) {  
        storeInfo.remove(key);  
        m_display.append("当前在线人数为:"+ storeInfo.size());
        //for(String name: storeInfo.key)
    }  

    // 将给定的消息转发给所有客户端  
    private synchronized void sendToAll(String message) {  
        for(PrintWriter out: storeInfo.values()) {  
            out.println(message);  


           // m_display.append("已经发送了");
        }  
    }  

    // 将给定的消息转发给私聊的客户端  
    private synchronized void sendToSomeone(String name,String message) {  
        PrintWriter pw = storeInfo.get(name); //将对应客户端的聊天信息取出作为私聊内容发送出去  
        if(pw != null) pw.println("私聊:     "+message);   
    }  

    public void start() {  
        try {  
            m_display.setVisible(true);
            //m_display.append("mayanshuo");
            while(true) { 

            m_display.append("等待客户端连接... ... \n"); 

            Socket socket = serverSocket.accept();  

            // 获取客户端的ip地址  
            InetAddress address = socket.getInetAddress();  
            m_display.append("客户端:“" + address.getHostAddress() + "”连接成功! ");  
            /* 
            * 启动一个线程,由线程来处理客户端的请求,这样可以再次监听 
            * 下一个客户端的连接 
            */  
            exec.execute(new ListenrClient(socket)); //通过线程池来分配线程  
            }  
        } catch(Exception e) {  
            e.printStackTrace();  
        }  
    }  

    /** 
    * 该线程体用来处理给定的某一个客户端的消息,循环接收客户端发送 
    * 的每一个字符串,并输出到控制台 
    */  
    class ListenrClient implements Runnable {  

        private Socket socket;  
        private String name;  

        public ListenrClient(Socket socket) {  
            this.socket = socket;  
        }  

        // 创建内部类来获取昵称  
        private String getName() throws Exception {  
            try {  
                //服务端的输入流读取客户端发送来的昵称输出流  
                BufferedReader bReader = new BufferedReader(  
                    new InputStreamReader(socket.getInputStream(), "UTF-8"));  
                //服务端将昵称验证结果通过自身的输出流发送给客户端  
                PrintWriter ipw = new PrintWriter(  
                    new OutputStreamWriter(socket.getOutputStream(), "UTF-8"),true);  

                //读取客户端发来的昵称  
                while(true) {  
                    String nameString = bReader.readLine();  
                    if ((nameString.trim().length() == 0) || storeInfo.containsKey(nameString)) {  
                        ipw.println("FAIL");  
                    } else {  
                        ipw.println("OK");  
                        return nameString;  
                    }  
                }  
            } catch(Exception e) {  
                throw e;  
            }  
        }  

        @Override         
        public void run() {  
            try {  
                /* 
                * 通过服务器端的socket分配给每一个 
                * 用来将消息发送给客户端 
                */  
                PrintWriter pw = new PrintWriter(  
                    new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);  

                /* 
                * 将客户昵称和其所说的内容存入共享集合HashMap中 
                */  
                name = getName();  
                putIn(name, pw);  
                Thread.sleep(100);  

                // 服务端通知所有客户端,某用户上线  
                sendToAll("*系统消息* “" + name + "”已上线");  

                /* 
                * 通过客户端的Socket获取输入流 
                * 读取客户端发送来的信息 
                */  
                BufferedReader bReader = new BufferedReader(  
                    new InputStreamReader(socket.getInputStream(), "UTF-8"));  
                String msgString = null;  


                while((msgString = bReader.readLine()) != null) {  
                    // 检验是否为私聊(格式:@昵称:内容)  
                    if(msgString.startsWith("@")) {  
                        int index = msgString.indexOf(":");  
                        if(index >= 0) {  
                            //获取昵称  
                            String theName = msgString.substring(1, index);  
                            String info = msgString.substring(index+1, msgString.length());  
                            info =  name + ":"+ info;  
                            //将私聊信息发送出去  
                            sendToSomeone(theName, info);

                            sendToSomeone(name,info);

                            continue;  
                        }  
                    }  
                    // 遍历所有输出流,将该客户端发送的信息转发给所有客户端  
                    m_display.append(name+":"+ msgString+"\n");  
                    sendToAll(name+":"+ msgString);  
                }     
            } catch (Exception e) {  
                // e.printStackTrace();  
            } finally {  
                remove(name);  
                // 通知所有客户端,某某客户已经下线  
                sendToAll("*系统消息* "+name + "已经下线了。\n");  

                if(socket!=null) {  
                    try {  
                        socket.close();  
                    } catch(IOException e) {  
                        e.printStackTrace();  
                    }  
                }     
            }  
        }  
    }  

    public static void main(String[] args) {  
        TCPServer server = new TCPServer();
        server.setSize(400,400);
        server.setVisible(true);
        server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        server.start();  
    }  
}  

2、客户端:

package server;

import java.io.*;  
import java.net.*;  
import java.util.Scanner;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ThreadPoolExecutor;  
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class TCPClient extends JFrame {  

    private JTextField m_enter=new JTextField();
    private JTextArea m_display=new JTextArea();
    private int m_count=0;
    private static  Socket clientSocket;  
    //private ExecutorService exec = Executors.newCachedThreadPool(); 
    private BufferedReader br;
    private PrintWriter pw;

    public TCPClient() 
    {
        super("聊天程序客户端");


        Container c=getContentPane();
        //m_enter.setSize(100,99);
        //m_display.setSize(200,100);
        m_enter.setVisible(true);
        m_display.setVisible(true);
        m_enter.requestFocusInWindow();     //转移输入焦点到输入区域

        //将光标放置在文本区域的尾部
        m_display.setCaretPosition(m_display.getText().length());


        c.add(m_enter,BorderLayout.SOUTH);
        c.add(new JScrollPane(m_display),BorderLayout.CENTER);  
        // this.add(panel);
        // this.setContentPane(jp);

    }  


    public static void main(String[] args) throws Exception {  
        TCPClient client = new TCPClient();
        client.setVisible(true);
        client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.setSize(470,708);
        client.start();  
    }  


    public void start() {  
        try {  
            m_display.append("请创建用户名:");
            clientSocket=new Socket("localhost",6666);
            BufferedReader br = new BufferedReader(  
                    new InputStreamReader(clientSocket.getInputStream(), "UTF-8")); 
            PrintWriter pw = new PrintWriter(  
                    new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true); 
            //ListenrServser l=new ListenrServser();
            m_enter.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent event)
                {
                    try{
                    String s=event.getActionCommand();
                    m_enter.setText("");
                     if(m_count==0)
                    {
                         pw.println(s);
                         m_display.append("\n'"+s+"'"+"昵称设置成功。\n");

                    }
                    else
                    {

                            pw.println(s);

                    }
                    m_count++;

                    }catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            });


            String msgString;
            while((msgString = br.readLine())!= null) {  
                m_display.append(msgString+"\n");  
            }  


        } catch(Exception e) {  
            e.printStackTrace();  
        } finally {  
            if (clientSocket !=null) {  
                try {  
                    clientSocket.close();  
                } catch(IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  



}  


运行结果:

1、这里是服务器端,显示当前连接人数,以及公聊信息:

2、此时为群内成员公聊:
这里创建了三个角色:马衍硕、李琦琦、小红。

 

 

3、私聊:
私聊格式“@名称:”+内容。
私聊时,只有私聊的两个人可以接收到信息,其余人接收不到交流信息。
例:马衍硕和李琦琦私聊,小红接收不到私聊信息。
马衍硕和李琦琦接收到了私聊信息:

 

 小红没有接收到私聊信息:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/224024.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Centos服务器上根据端口号查询jar包,根据jar包查端口号

在开发springboot服务器时&#xff0c;经常会遇到其他人部署的java服务&#xff0c;需要自己维护&#xff0c;留下的信息又非常少。经常面临找不到jar包位置&#xff0c;或者不知道占用端口&#xff0c;不知道启动命令的问题。这里记录一下常用的centos服务器上的命令&#xff…

【桑基图】绘制桑基图

绘制桑基图 一、绘制桑基图&#xff08;1&#xff09;方法一&#xff1a;去在线网站直接绘制&#xff08;2&#xff09;方法二&#xff1a;写html之后在vscode上运行 二、遇到的问题&#xff08;1&#xff09;当导入一些excel的时候&#xff0c;无法绘制出桑基图 一、绘制桑基图…

ROS-ROS通信机制-参数服务器

文章目录 一、基础理论知识二、C实现三、Python实现 一、基础理论知识 参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器&#xff0c;可以将数据存储在该容器中&#xff0c;被不同的节点调用&#xff0c;当然不同的节点…

【LeetCode刷题】-- 79.单词搜索

79.单词搜索 方法&#xff1a;使用回溯 使用dfs函数表示判断以网格的(i.j)位置出发&#xff0c;能否搜索到word(k)&#xff0c;其中word(k)表示字符串word从第k个字符开始的后缀子串&#xff0c;如果能搜索到&#xff0c;返回true,反之返回false 如果board[i][j]≠word[k]&am…

李宏毅gpt个人记录

参考&#xff1a; 李宏毅机器学习--self-supervised&#xff1a;BERT、GPT、Auto-encoder-CSDN博客 用无标注资料的任务训练完模型以后&#xff0c;它本身没有什么用&#xff0c;GPT 1只能够把一句话补完&#xff0c;可以把 Self-Supervised Learning 的 Model做微微的调整&am…

分享一个Python网络爬虫数据采集利器

前言 你是否曾为获取重要数据而感到困扰&#xff1f;是否因为数据封锁而无法获取所需信息&#xff1f;是否因为数据格式混乱而头疼&#xff1f;现在&#xff0c;所有这些问题都可以迎刃而解。让我为大家介绍一款强大的数据收集平台——亮数据Bright Data。 作为世界领先的数据…

【Qt】QLineEdit显示输入十六进制,位数不足时按照规则填充显示及每两个字符以空格填充

问题 在实际开发中&#xff0c;有时候需要对输入进行限制&#xff0c;一是更加合理&#xff0c;二是防止出现误操作。 比如&#xff1a; 使用Qt进行应用程序开发时&#xff0c;对单行编辑框QLineEdit控件&#xff0c;设置只可输入十六进制。 限制输入的方式常用且经典的是使用…

限流算法,基于go的gRPC 实现的

目录 一、单机限流 1、令牌桶算法 3、固定窗口限流算法 4、滑动窗口 二、集群限流 1、分布式固定窗口 &#xff08;基于redis&#xff09; 2、分布式滑动窗口 一、单机限流 1、令牌桶算法 令牌桶算法是当流量进入系统前需要获取令牌&#xff0c;没有令牌那么就要进行限…

Docker+jenkins+gitlab实现持续集成

1.安装环境 服务器ip虚拟机版本192.168.5.132centos7.6192.168.5.152centos7.6 2. 安装docker 安装必要的一些系统工具 yum install -y yum-utils device-mapper-persistent-data lvm2添加软件源信息&#xff0c;要确保centos7能上外网 yum-config-manager --add-repo http:…

什么是数据清洗、特征工程、数据可视化、数据挖掘与建模?

1.1什么是数据清洗、特征工程、数据可视化、数据挖掘与建模&#xff1f; 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.1节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵…

智篆商业的电商运营课程:超越传统,引领未来

智篆商业一直以来都是电商运营课程领域的领军者&#xff0c;其成功之处在于超越传统&#xff0c;不断引领未来。探究智篆商业的成功之道&#xff0c;我们将发现其可信度和培训专业性是学员信赖的根本原因。 首先&#xff0c;智篆商业注重构建强大的导师团队。导师们不仅拥有丰富…

持续集成交付CICD:Jenkins使用GitLab共享库实现自动更新前后端项目质量配置

目录 一、实验 1.Jenkins使用GitLab共享库实现自动更新后端项目质量配置 2.Jenkins使用GitLab共享库实现自动更新前端项目质量配置 二、问题 1.Sonarqube如何添加自定义质量阈 一、实验 1.Jenkins使用GitLab共享库实现自动更新后端项目质量配置 (1)修改GitLab的Sonar.gr…

HBase-架构与设计

HBase架构与设计 一、背景二、HBase概述1.设计特点2.适用场景2.1 海量数据2.2 稀疏数据2.3 多版本数据2.4 半结构或者非结构化数据 三、数据模型1.RowKey2.Column Family3.TimeStamp 四、HBase架构图1.Client2.Zookeeper3.HMaster4.HRegionServer5.HRegion6.Store7.StoreFile8.…

flink使用事件时间时警惕kafka不同分区的事件时间倾斜问题

背景 flink和kafka的消息组合消费模式几乎是实时流处理的标配&#xff0c;然后当在flink中使用事件时间处理时&#xff0c;需要注意kafka不同分区元素之间时间相差太大的问题&#xff0c;这样有可能会导致严重的数据堆积问题 kafka不同分区元素事件时间差异较大导致的问题 总…

分布式光伏电站监控运维系统的简单介绍-安科瑞黄安南

摘要&#xff1a;设计了一套更高性价比&#xff0c;且容易操作的电站监控系统。该系统融合了互联网和物联网&#xff0c;并为光伏电数据的传输构建了相应的通道&#xff0c;可支持云存储等功能&#xff0c;同时也为用户提供了多元化的查询功能。 关键词&#xff1a;分布式太阳能…

gitLab 和Idea分支合并

以下二选1即可完成分支合并建议第一种简单有效 Idea合并方式 切换到被合并的分支&#xff0c;如我想把0701的内容合并到dev&#xff0c;切换到dev分支&#xff0c;然后再点击merge然后选择要合并的分支&#xff0c;即可,此时git上的代码没有更新只是把代码合到本地需要pull才…

ELK的日志解决方案

ELK的日志解决方案 一、ELK 介绍 ELK是一个流行的日志解决方案&#xff0c;它由三个开源工具组成&#xff1a;Elasticsearch、Logstash和Kibana。下面是这些工具的简单介绍以及它们在日志解决方案中的作用&#xff1a; Elasticsearch&#xff1a;Elasticsearch是一个分布式的搜…

设置webstorm和idea符合Alibaba规范

只格式化自己更改的代码 ctrlShiftAltL 插件建议 Alibaba Java Coding Guidelines&#xff08;新版本的idea不支持&#xff0c;有其他同名的非官方版可代替&#xff09;&#xff0c;使用方法在此不赘述 1、设置webstorm 包含 设置两个空格缩进&#xff0c;去掉行尾分号&#…

IDEA加载阿里Java规范插件

IDEA加载阿里巴巴Java开发手册插件&#xff0c;在写代码的时候会自动扫描代码规范。 1、打开Settings 2、打开Plugins 3、搜索Alibaba Java Code Guidelines&#xff08;XenoAmess TPM&#xff09;插件&#xff0c;点击Install进行安装&#xff0c;然后重启IDE生效。 4、鼠标右…

基于OpenCV+CNN+IOT+微信小程序智能果实采摘指导系统——深度学习算法应用(含pytho、JS工程源码)+数据集+模型(二)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境Jupyter Notebook环境Pycharm 环境微信开发者工具OneNET云平台 相关其它博客工程源代码下载其它资料下载 前言 本项目基于Keras框架&#xff0c;引入CNN进行模型训练&#xff0c;采用Dropout梯度…