Linux网络套接字之UDP网络程序

news/2024/5/18 12:35:48 标签: 网络, linux, udp

 (。・∀・)ノ゙嗨!你好这里是ky233的主页:这里是ky233的主页,欢迎光临~icon-default.png?t=N7T8https://blog.csdn.net/ky233?type=blog

点个关注不迷路⌯'▾'⌯

 实现一个简单的对话发消息的功能!

目录

一.新增的接口:

1.socket

2.bing

3.inet_addr

4.recvform

5.inet_ntoa

5.sendto

6.popen

二、初步代码以及结果

udp_server.hpp-toc" style="margin-left:40px;">1.udp_server.hpp

udp_server.cc%C2%A0-toc" style="margin-left:40px;">2.udp_server.cc 

udp_client-toc" style="margin-left:40px;">3.udp_client

4.log.hpp

5.结果 

三、爆改多线程

udp_client.cc-toc" style="margin-left:40px;">1.udp_client.cc

udp_server.cc-toc" style="margin-left:40px;">2.udp_server.cc

udp_server.hpp-toc" style="margin-left:40px;">3.udp_server.hpp

 4.thread.hpp

5.结果


一.新增的接口:

1.socket

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

       int socket(int domain, int type, int protocol);
  • 参数一:叫做域,用来判断是那个类型的,AF_UNIX, AF_LOCAL(用于本地通信)AF_INET(用于ipv4的网络通信)
  • 参数二:类型,通信的种类是什么,SOCK_DGRAM(套接字的类别,数据报的方式)
  • 参数三:协议,比如用AF_INET,SOCK_DGRAM,一般直接写0
  •  创建成功会得到一个文件描述符,失败返回-1

2.bing

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
  • 参数一:创建的套接字
  • 参数二:填充sockaddr结构体
  • 参数三:所传入这个结构体对象的长度

3.inet_addr

#include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>
n_addr_t inet_addr(const char *cp);
  • 将点分十进制转换成四字节,并且将主机序列转换成网络序列
  • 参数一:传入的ip

4.recvform

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
  • 用于从套接字接收数据。该函数通常与无连接的数据报服务
  • 参数一:套接字
  • 参数二和参数三:读取数据的缓冲区,用于存放读取到的数据,len叫做最终的大小
  • 参数四:读取的方式,0为阻塞的方式读取
  • 参数五和参数六:是输出型参数,我们还要知道是谁给我们发的消息

5.inet_ntoa

#include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>
char *inet_ntoa(struct in_addr in);
  • 将点分四字节转换成点分十进制,并且将网络序列转换成主机序列
  • 参数一:从网络中获取到的ip

5.sendto

#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
  • 参数一:套接字
  • 参数二和参数三:要发送的数据和长度
  • 参数四:默认为0,阻塞
  • 参数五:要把数据发给谁,
  • 参数六:这个缓冲区的长度是多少

6.popen

#include <stdio.h>

       FILE *popen(const char *command, const char *type);

二、初步代码以及结果

udp_server.hpp">1.udp_server.hpp

#ifndef _UDP_SERVER_HPP
#define _UDP_SERVER_HPP

#include <iostream>
#include <string>
#include <sys/types.h>        
#include <sys/socket.h>
#include "log.hpp"
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <cstdio>
#include <unistd.h>


#define SIZE 1024

class UDPServer
{
public:
    UDPServer(uint16_t port,std::string ip="")
    :port_(port),ip_(ip),sock_(-1)
    {}

    bool initServer()
    {
        //这里开始使用网络部分
        //1.创建套接字
        sock_=socket(AF_INET,SOCK_DGRAM,0);
        if(sock_<0)
        {
            logMessage(FATAL,"%d:%s",errno,strerror(errno));
            exit(2);
        }
        //2.bind绑定:将用户设置的ip和端口号在内核中和我们的进程强关联
        //"192.168.1.0"->点分十进制
        //以.来分隔,每个区域的取值范围为0——255,
        //正好为1字节,四个区域理论上需要四字节
        //所以我们的看的时候会由4字节显示,转换为点分十进制
        
        //初始化结构体完成
        struct sockaddr_in local;
        bzero(&local,sizeof(local));
        //填充结构体
        local.sin_family=AF_INET;
        //服务器的IP和端口号,未来也是要发送给对方主机才能互相通信的
        //所以要先把数据发送到网络,要用htons
        local.sin_port=htons(port_);
        //同上要先把点分十进制转换成四字节ip
        //还需要要把四字节主机序列,转换成网络序列
        //所以用inet_addr一次性转成网络四字节序列
        //local.sin_addr.s_addr=inet_addr(ip_.c_str());
        //一般情况下,只要是这个端口的,那么我们就直接全部都接受,而不是指定端口
        local.sin_addr.s_addr = ip_.empty() ? INADDR_ANY : inet_addr(ip_.c_str());
        //这里需要做强转,因为bind需要的是sockaddr类型而不是sockaddr_in类型
        if(bind(sock_,(struct sockaddr*)&local,sizeof(local))<0)
        {
            logMessage(FATAL,"%d:%s",errno,strerror(errno));
            exit(2);
        }
        //至此初始化服务器写完,首先创建套接字,接着用bind来绑定ip和端口号写进内核中
        logMessage(NORMAL, "init udp server done ... %s", strerror(errno));
        return true;
    }

    void strat()
    {
        //作为一款网络服务器,是永远不退出的!
        // 服务器启动-> 进程 -> 常驻进程 -> 永远在内存中存在,除非挂了!
        //echo服务器,主机给我们发送消息,我们原封不动的返回
        char buffer[SIZE];
        for( ; ;)
        {
            //1.读取数据
            //注意peer,纯输出型参数
            struct sockaddr_in peer;
            bzero(&peer,sizeof(peer));
            //输入:peer 缓冲区大小
            //输入:实际读到的peer大小
            //所以len的大小要为实际的peer大小
            socklen_t len = sizeof(peer);
            //这样就把数据读取到buffer里了
            ssize_t s= recvfrom(sock_,&buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
            if(s>0)
            {
                buffer[s]=0;//我们目前数据当作字符串
                //1.输出发送的数据信息
                //2.是谁?提取!
                uint16_t cil_port=ntohs(peer.sin_port);//从网络中来的,所以要进行转成主机端口号
                std::string cli_p=inet_ntoa(peer.sin_addr);//将点分四字节转换成点分十进制,并且将网络序列转换成主机序列
                printf("[%s:%d]# %s\n",cli_p.c_str(),cil_port,buffer);
            }
            //2.分析和处理数据

            //3.写回数据
            sendto(sock_,buffer,sizeof(buffer),0,(struct sockaddr*)&peer,len);
        }
    }

    ~UDPServer()
    {
        if(sock_>=0)
        {
            close(sock_);
        }
    }

private:
uint16_t port_;
std::string ip_;
int sock_;
};

#endif

udp_server.cc%C2%A0">2.udp_server.cc 

#include "udp_server.hpp"
#include <memory>
#include <cstdlib>

static void usage(std::string proc)
{
    std::cout << "\nUsage: " << proc << " port\n" << std::endl;
}

int main(int argc,char *argv[])
{
    //检查传入ip和端口号是否错误
    if(argc!=2)
    {
        usage(argv[0]);
        exit(1);

    }
    //初始化服务器,利用unique_ptr
    uint16_t port=atoi(argv[1]);
    //std::string ip=argv[1];
    std::unique_ptr<UDPServer> svr(new UDPServer(port));
    svr->initServer();
    svr->strat();
    return 0;
}

udp_client">3.udp_client

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <memory>
#include "thread.hpp"

static void usage(std::string proc)
{
    std::cout << "\nUsage: " << proc << " serverIp serverPort\n"
              << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(1);
    }
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        
        std::cerr << "socket error" << std::endl;
        exit(2);
    }
    //client要不要bind?要bind,但是client不会显示的bind,程序员不会自己bind
    //client是一个客户端,是普通人下载并使用的
    //如果需要显示的bind,也就要求了客户端也bind了一个固定的端口
    //万一其他的客户端提前真用了端口号了呢,这时这个客户端就无法启动了
    //所以不用显示的bind指定端口号,直接让OS自动随机选择
    std::string message;
    //给谁发的信息如下
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(atoi(argv[2]));
    server.sin_addr.s_addr=inet_addr(argv[1]);

    char buffer[1024];
    while(1)
    {
        std::cout<<"请输入你的信息# ";
        std::getline(std::cin,message);
        if(message=="quit")
        {
            break;
        }
        //当client首次发送消息给服务器的时候,OS会自动给client bind它的ip和port
        sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));
        //至此客户端和服务器已经建成

        //这里需要定义两个占位的
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t s= recvfrom(sock,&buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);
        if(s>0)
        {
            buffer[s]=0;
            std::cout<<"server echo# "<<buffer<<std::endl;
        }

    }
    close(sock);
    return 0;
}

4.log.hpp

#pragma once

#include <iostream>
#include <cstdio>
#include <cstdarg>
#include <ctime>
#include <string>

// 日志是有日志级别的
#define DEBUG   0
#define NORMAL  1
#define WARNING 2
#define ERROR   3
#define FATAL   4

const char *gLevelMap[] = {
    "DEBUG",
    "NORMAL",
    "WARNING",
    "ERROR",
    "FATAL"
};

#define LOGFILE "./threadpool.log"

// 完整的日志功能,至少: 日志等级 时间 支持用户自定义(日志内容, 文件行,文件名)
void logMessage(int level, const char *format, ...)
{
#ifndef DEBUG_SHOW
    if(level== DEBUG) return;
#endif
    // va_list ap;
    // va_start(ap, format);
    // while()
    // int x = va_arg(ap, int);
    // va_end(ap); //ap=nullptr
    char stdBuffer[1024]; //标准部分
    time_t timestamp = time(nullptr);
    // struct tm *localtime = localtime(&timestamp);
    snprintf(stdBuffer, sizeof stdBuffer, "[%s] [%ld] ", gLevelMap[level], timestamp);

    char logBuffer[1024]; //自定义部分
    va_list args;
    va_start(args, format);
    // vprintf(format, args);
    vsnprintf(logBuffer, sizeof logBuffer, format, args);
    va_end(args);

    //FILE *fp = fopen(LOGFILE, "a");
    printf("%s%s\n", stdBuffer, logBuffer);
    //fprintf(fp, "%s%s\n", stdBuffer, logBuffer);
    //fclose(fp);
}

5.结果 

这个叫做本地环回:client和server发送数据只在本地协议栈中进行数据流动,不会把我们的数据发送到网络中,通常用于本地网络服务器的测试

 ——————————————————————————————————————————

其中客户端时OS随机绑定的,全0IP是因为只要是这个端口的我都要,不要具体IP的

三、爆改多线程

我们要把这个代码改成一个类似QQ群一样的模式,所有人发的消息都可以看到

udp_client.cc">1.udp_client.cc

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <memory>
#include "thread.hpp"

uint16_t serverport=0;
std::string serverip;

//发现:无论是多线程读还是写,用的sock都是一个,sock代表就是文件,UDP是全双工的-> 可以同时进行收发而不受干扰


static void usage(std::string proc)
{
    std::cout << "\nUsage: " << proc << " serverIp serverPort\n"
              << std::endl;
}

//发送逻辑的回调
static void *udpSend(void *args)
{
    //根据线程的封装,先转换成data*的然后获取里面的args_,然后在转会int*
    //获得一个指针指向args里面的sock,然后解引用
    int sock=*(int*)((ThreadData*)args)->args_;
    std::string name = ((ThreadData*)args)->name_;
    //下面逻辑与之前一样,构建发送的字符串,套接字信息
    std::string message;
    //给谁发的信息如下
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(serverport);
    server.sin_addr.s_addr=inet_addr(serverip.c_str());

    //开始不间断的发送
    while(1)
    {
        std::cerr<<"请输入你的信息# ";
        std::getline(std::cin,message);
        if(message=="quit")
        {
            break;
        }
        //当client首次发送消息给服务器的时候,OS会自动给client bind它的ip和port
        sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));
        //至此客户端和服务器已经建成
    }
    return nullptr;
}

//接受逻辑的回调
static void *udpRecv(void *args)
{
    int sock=*(int*)((ThreadData*)args)->args_;
    std::string name = ((ThreadData*)args)->name_;

    //需要不断地去读,要去指定的套接字中读取
    while(1)
    {
        char buffer[1024];
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t s= recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);
        if(s>0)
        {
            buffer[s]=0;
            std::cout<<buffer<<std::endl;
        }

    }
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(1);
    }
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        
        std::cerr << "socket error" << std::endl;
        exit(2);
    }

    serverport=atoi(argv[2]);
    serverip=argv[1];
    //client要不要bind?要bind,但是client不会显示的bind,程序员不会自己bind
    //client是一个客户端,是普通人下载并使用的
    //如果需要显示的bind,也就要求了客户端也bind了一个固定的端口
    //万一其他的客户端提前真用了端口号了呢,这时这个客户端就无法启动了
    //所以不用显示的bind指定端口号,直接让OS自动随机选择

    //爆改多线程,一个线程发送数据到各个主机,一个线程接受各个数据。
    std::unique_ptr<Thread> sender(new Thread(1,udpSend,(void*)&sock));
    std::unique_ptr<Thread> recver(new Thread(2,udpRecv,(void*)&sock));

    sender->start();
    recver->start();

    sender->join();
    recver->join();
    close(sock);



    // std::string message;
    // //给谁发的信息如下
    // struct sockaddr_in server;
    // memset(&server,0,sizeof(server));
    // server.sin_family=AF_INET;
    // server.sin_port=htons(atoi(argv[2]));
    // server.sin_addr.s_addr=inet_addr(argv[1]);

    // char buffer[1024];
    // while(1)
    // {
    //     std::cout<<"请输入你的信息# ";
    //     std::getline(std::cin,message);
    //     if(message=="quit")
    //     {
    //         break;
    //     }
    //     //当client首次发送消息给服务器的时候,OS会自动给client bind它的ip和port
    //     sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));
    //     //至此客户端和服务器已经建成

    //     //这里需要定义两个占位的
    //     struct sockaddr_in temp;
    //     socklen_t len = sizeof(temp);
    //     ssize_t s= recvfrom(sock,&buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);
    //     if(s>0)
    //     {
    //         buffer[s]=0;
    //         std::cout<<"server echo# "<<buffer<<std::endl;
    //     }

    // }
    // close(sock);
    return 0;
}

udp_server.cc">2.udp_server.cc

#include "udp_server.hpp"
#include <memory>
#include <cstdlib>

static void usage(std::string proc)
{
    std::cout << "\nUsage: " << proc << " port\n" << std::endl;
}

int main(int argc,char *argv[])
{
    //检查传入ip和端口号是否错误
    if(argc!=2)
    {
        usage(argv[0]);
        exit(1);

    }
    //初始化服务器,利用unique_ptr
    uint16_t port=atoi(argv[1]);
    //std::string ip=argv[1];
    std::unique_ptr<UDPServer> svr(new UDPServer(port));
    svr->initServer();
    svr->strat();
    return 0;
}

udp_server.hpp">3.udp_server.hpp

#ifndef _UDP_SERVER_HPP
#define _UDP_SERVER_HPP

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include "log.hpp"
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <cstdio>
#include <unistd.h>
#include <unordered_map>

#define SIZE 1024

class UDPServer
{
public:
    UDPServer(uint16_t port, std::string ip = "")
        : port_(port), ip_(ip), sock_(-1)
    {
    }

    bool initServer()
    {
        // 这里开始使用网络部分
        // 1.创建套接字
        sock_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock_ < 0)
        {
            logMessage(FATAL, "%d:%s", errno, strerror(errno));
            exit(2);
        }
        // 2.bind绑定:将用户设置的ip和端口号在内核中和我们的进程强关联
        //"192.168.1.0"->点分十进制
        // 以.来分隔,每个区域的取值范围为0——255,
        // 正好为1字节,四个区域理论上需要四字节
        // 所以我们的看的时候会由4字节显示,转换为点分十进制

        // 初始化结构体完成
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        // 填充结构体
        local.sin_family = AF_INET;
        // 服务器的IP和端口号,未来也是要发送给对方主机才能互相通信的
        // 所以要先把数据发送到网络,要用htons
        local.sin_port = htons(port_);
        // 同上要先把点分十进制转换成四字节ip
        // 还需要要把四字节主机序列,转换成网络序列
        // 所以用inet_addr一次性转成网络四字节序列
        // local.sin_addr.s_addr=inet_addr(ip_.c_str());
        // 一般情况下,只要是这个端口的,那么我们就直接全部都接受,而不是指定端口
        local.sin_addr.s_addr = ip_.empty() ? INADDR_ANY : inet_addr(ip_.c_str());
        // 这里需要做强转,因为bind需要的是sockaddr类型而不是sockaddr_in类型
        if (bind(sock_, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            logMessage(FATAL, "%d:%s", errno, strerror(errno));
            exit(2);
        }
        // 至此初始化服务器写完,首先创建套接字,接着用bind来绑定ip和端口号写进内核中
        logMessage(NORMAL, "init udp server done ... %s", strerror(errno));
        return true;
    }

    void strat()
    {
        // 作为一款网络服务器,是永远不退出的!
        //  服务器启动-> 进程 -> 常驻进程 -> 永远在内存中存在,除非挂了!
        // echo服务器,主机给我们发送消息,我们原封不动的返回
        char buffer[SIZE];
        for (;;)
        {
            // 1.读取数据
            // 注意peer,纯输出型参数
            struct sockaddr_in peer;
            bzero(&peer, sizeof(peer));
            // 输入:peer 缓冲区大小
            // 输入:实际读到的peer大小
            // 所以len的大小要为实际的peer大小
            socklen_t len = sizeof(peer);
            // 这样就把数据读取到buffer里了
            ssize_t s = recvfrom(sock_, &buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
            char result[256];
            char key[64];
            std::string cmd_echo;
            if (s > 0)
            {
                buffer[s] = 0; // 我们目前数据当作字符串
                // 1.输出发送的数据信息
                // 2.是谁?提取!
                // if(strcasestr(buffer,"rm")!=nullptr||strcasestr(buffer,"rmdir")!=nullptr)
                // {
                //     std::string err_message="坏人";
                //     std::cout<<err_message<<buffer<<std::endl;
                //     sendto(sock_, err_message.c_str(), err_message.size(), 0, (struct sockaddr *)&peer, len);

                //     continue;
                // }
                // FILE *fp = popen(buffer, "r");
                // if (nullptr == fp)
                // {
                //     logMessage(ERROR, "%d:%s", errno, strerror(errno));
                //     continue;
                // }

                // while (fgets(result, sizeof(result), fp) != nullptr)
                // {
                //     cmd_echo += result;
                // }
                // fclose(fp);
                uint16_t cil_port = ntohs(peer.sin_port);     // 从网络中来的,所以要进行转成主机端口号
                std::string cil_ip = inet_ntoa(peer.sin_addr); // 将点分四字节转换成点分十进制,并且将网络序列转换成主机序列
                // printf("[%s:%d]# %s\n",cli_p.c_str(),cil_port,buffer);
                snprintf(key, sizeof(key), "%s-%d", cil_ip.c_str(), cil_port);
                logMessage(NORMAL,"key: %s",key);
                auto it = users_.find(key);
                if(it==users_.end())
                {
                    logMessage(NORMAL,"add new user:%s",key);
                    users_.insert({key,peer});
                }

            }
            // 2.分析和处理数据

            // 3.写回数据
            // sendto(sock_,buffer,sizeof(buffer),0,(struct sockaddr*)&peer,len);
            //sendto(sock_, cmd_echo.c_str(), cmd_echo.size(), 0, (struct sockaddr *)&peer, len);
            for(auto &iter:users_)
            {
                std::string sendMessage=key;
                sendMessage+="# ";
                sendMessage+=buffer;
                logMessage(NORMAL,"push message to %s",iter.first.c_str());
                sendto(sock_, sendMessage.c_str(), sendMessage.size(), 0, (struct sockaddr *)&(iter.second), sizeof(iter.second));

            }
        }
    }

    ~UDPServer()
    {
        if (sock_ >= 0)
        {
            close(sock_);
        }
    }

private:
    uint16_t port_;
    std::string ip_;
    int sock_;
    std::unordered_map<std::string, struct sockaddr_in> users_;
};

#endif

 4.thread.hpp

#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <cstdio>

using namespace std;

typedef void*(*fun_t)(void*);

class ThreadData
{
public:
    void* args_;
    string name_;
};

class Thread
{
public:
    Thread(int num,fun_t callback,void* args):func_(callback)
    {
        char namebuffer[64];
        snprintf(namebuffer,sizeof(namebuffer),"Thread-%d",num);
        name_=namebuffer;

        tdata_.args_=args;
        tdata_.name_=name_;
    }

    void start()
    {
        pthread_create(&tid_,nullptr,func_,&tdata_.args_);
    }

    void join()
    {
        pthread_join(tid_,nullptr);
    }
    
    string name()
    {
        return name_;
    }
    ~Thread()
    {

    }

private:
    string name_;
    fun_t func_;
    ThreadData tdata_;
    pthread_t tid_;
};

5.结果

利用管道可以更好的观看


http://www.niftyadmin.cn/n/5417967.html

相关文章

微信私信短剧机器人源码

本源码仅提供参考&#xff0c;有能力的继续开发 接口为api调用 云端同步 https://ys.110t.cn/api/ajax.php?actyingshilist 影视搜索 https://ys.110t.cn/api/ajax.php?actsearch&name剧名 每日更新 https://ys.110t.cn/api/ajax.php?actDaily 反馈接口 https://ys.11…

云计算项目十一:构建完整的日志分析平台

检查k8s集群环境&#xff0c;master主机操作&#xff0c;确定是ready 启动harbor [rootharbor ~]# cd /usr/local/harbor [rootharbor harbor]# /usr/local/bin/docker-compose up -d 检查head插件是否启动&#xff0c;如果没有&#xff0c;需要启动 [rootes-0001 ~]# system…

Mac安装oh-my-zsh

目录 命令下载 卸载命令 注意 命令下载 curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh 卸载命令 uninstall_oh_my_zsh 注意 终端init的时候并不会执行~/.bash_profile、~/.bashrc等脚本了&#xff0c; 这是因为其默认启动执行脚本…

ChatGPT 串接到 Discord - 团队协作好助理

ChatGPT 串接到 Discord - 团队协作好助理 ChatGPT 是由 OpenAI 开发的一个强大的语言模型&#xff0c;本篇文章教你如何串接 Discord Bot &#xff0c;协助团队在工作上更加高效并促进沟通与协作。使 ChatGPT 发挥出最大的功效&#xff0c;进一步提升工作效率和团队协作能力。…

CentOS 7升级openssh9.6p1

一、环境情况 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]# ssh -V OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017二、准备 1. 开启telnet 主要是在安装过程中&#xff0c;需要卸载老版本openssh&#xff0c;临…

AWS的CISO:GenAI只是一个工具,不是万能钥匙

根据CrowdStrike的年度全球威胁报告,尽管研究人员预计人工智能将放大对防御者和攻击者的影响,但威胁参与者在其行动中使用人工智能的程度有限。该公司上个月在报告中表示:“在整个2023年,很少观察到GenAI支持恶意计算机网络运营的开发和/或执行。” 对于GenAI在网络安全中的…

GPT实战系列-LangChain如何构建基通义千问的多工具链

GPT实战系列-LangChain如何构建基通义千问的多工具链 LLM大模型&#xff1a; GPT实战系列-探究GPT等大模型的文本生成 GPT实战系列-Baichuan2等大模型的计算精度与量化 GPT实战系列-GPT训练的Pretraining&#xff0c;SFT&#xff0c;Reward Modeling&#xff0c;RLHF GPT实…

Ubuntu平铺左、右、上、下、1/2、1/4窗口(脚本)

前言 之前因为一直在用Ubuntu 18或者Ubuntu 20然后发现装了GNOME插件后&#xff0c;电脑在使用过程中&#xff0c;会时不时的卡死&#xff08;鼠标没问题&#xff0c;键盘输入会有10-20秒的延迟&#xff09;频率基本是一小时一次&#xff0c;因为这种卡顿会很容易打断思路&…