首页 > 系统相关 >【linux网络编程】| socket套接字 | 实现UDP协议聊天室

【linux网络编程】| socket套接字 | 实现UDP协议聊天室

时间:2024-10-29 23:15:46浏览次数:3  
标签:UDP socket errno linux sockfd UdpServer include local 服务端

        前言:本节内容将带友友们实现一个UDP协议的聊天室。 主要原理是客户端发送数据给服务端。 服务端将数据再转发给所有链接服务端的客户端。 所以, 我们主要就是要实现客户端以及服务端的逻辑代码。 那么, 接下来开始我们的学习吧。

        ps:本节内容建议了解socket套接字的接口的友友们进行观看哦,本节内容中涉及到的接口都不会讲解, 直接就用了。

目录

 整体代码

Udpclient

UdpServer

main(配合UdpServer, UdpServer的入口) 

准备文件

实现步骤

实现服务端客户端的收发消息

Udpserver

Init函数

run函数 

 UdpServer析构

Udpclient

实现客户端之间的聊天功能

Udpserver

Udpclient

运行结果


 整体代码

        先上整体代码:

Udpclient


#include<iostream>
using namespace std;
#include<string>
#include<sys/types.h>
#include"Log.hpp"
#include<sys/socket.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>
#include<netinet/in.h>
Log lg;


class ThreadData
{
public:
    sockaddr_in server;
    int sockfd;
};

void* recv_message(void* args)
{
    char buffer[1024];
    ThreadData* td = static_cast<ThreadData*>(args);    
    while (true)
    {
        //接收数据
        sockaddr_in temp;
        socklen_t len;
        string info;
        ssize_t s = recvfrom(td->sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &len);

        if (s < 0)
        {
            lg(Error, "recv error, error: %d, strerror: %s", errno, strerror(errno));
            continue;
        }
        buffer[s] = 0;
        info = buffer;
        cout << info << endl;
    }

}

void* send_message(void* args)
{
    ThreadData* td = static_cast<ThreadData*>(args);
    string message;
    while (true)
    { 
        getline(cin, message);  //获取数据
        //发送数据
        sendto(td->sockfd, message.c_str(), message.size(), 0, (sockaddr*)&td->server, sizeof(td->server));

    }
}

int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        cout << "Client server" << endl;
    }

    //先拿到套接字的参数
    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    ThreadData td;

    //创建套接字与打开网卡
    memset(&td.server, 0, sizeof(td.server));
    td.server.sin_family = AF_INET;
    td.server.sin_port = htons(serverport);
    td.server.sin_addr.s_addr = inet_addr(serverip.c_str());
    td.sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建文件描述符, 网卡的文件描述符, 网络传输就是使用网络文件描述符找到对应的文件内的数据
    if (td.sockfd < 0)
    {
        lg(Error, "client create sockfd error, errno: %d, strerror: %s", errno, strerror(errno));
        exit(1);
    }

    //创建线程, 然后运行线程, 等待线程
    pthread_t recv, send;
    pthread_create(&recv, nullptr, recv_message, &td);
    pthread_create(&send, nullptr, send_message, &td);

    pthread_join(recv, nullptr);
    pthread_join(send, nullptr);

    close(td.sockfd);
    return 0;
}

UdpServer

#include<iostream>
using namespace std;
#include<sys/types.h>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include"Log.hpp"
#include<functional>
#include<netinet/in.h>
#include<unordered_map>


int defaultport = 8080;
string defaultip = "0.0.0.0";

using func_t = function<string(string, sockaddr_in&, unordered_map<string, sockaddr_in>&)>; 
Log lg;

enum
{
    SockError = 2,
    BindError = 3,
    RecvError = 4,
};

class UdpServer
{
public:
    UdpServer(uint16_t port = defaultport) 
        : port_(port), ip_(defaultip), isrunning_(false)
    {}

    void Init()
    {
        //先创建套接字变量并且完成初始化。 然后就创建网卡文件
        sockaddr_in local;
        
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        local.sin_addr.s_addr = inet_addr(ip_.c_str());
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd_ < 0)
        {
            lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));
            exit(SockError);
        }
        lg(Info, "create sock success");
        
        //绑定
        if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) 
        {
            lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));
            exit(BindError);
        }
        lg(Info, "bind success");
    }

    void BroadCast(string message, unordered_map<string, sockaddr_in>& clients)
    {
        cout << "1 "<< endl;
        for (auto& e : clients)
        {
            sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&e.second, sizeof(e.second));
        }
        cout << "2 " << endl;
    }

    
    void run(func_t func)
    {
        isrunning_ = true;
        char inbuffer[1024];


        while (isrunning_)
        {
            memset(inbuffer, 0, sizeof(inbuffer));
            sockaddr_in client;
            socklen_t client_len;
            memset(&client, 0, sizeof(client));
            //接收数据的同时监听到客户端的来源
            ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);
            if (s < 0) 
            {
                lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));
                continue;
            }
            inbuffer[s] = 0;

            //处理数据
            //创建套接字, 用来监听是哪一个客户端

            string message = inbuffer;
            message = func(message, client, clients);

            //处理完成后, 返回发送给客户端
            BroadCast(message, clients);
            // sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&client, sizeof(client));


        }
    }

    ~UdpServer()
    {
        if (sockfd_ > 0) close(sockfd_);    
    }
private:
    int sockfd_;
    uint16_t port_;
    string ip_;
    bool isrunning_;
    unordered_map<string, sockaddr_in> clients;

};

main(配合UdpServer, UdpServer的入口) 


#include"UdpServer.hpp"
#include<memory>

string Handler(string message, sockaddr_in& client, unordered_map<string, sockaddr_in>& clients)
{
    string tmp = inet_ntoa(client.sin_addr) + to_string(client.sin_port);
    if (!clients.count(tmp))
    {
        clients[tmp] = client; 
        cout << "ip " << inet_ntoa(client.sin_addr) << " : port " << client.sin_port << " has add in talk room" << endl;
    }
    message = "[" + string(inet_ntoa(client.sin_addr)) + ":" + to_string(client.sin_port) + "]#: " + message; 
    return message;
}

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        cout << "has return" << endl;
        return 1;
    }
    //
    uint16_t serverport = stoi(argv[1]);  

    unique_ptr<UdpServer> svr(new UdpServer(serverport));
    //
    svr->Init();
    svr->run(Handler);


    return 0;
}

准备文件

        我们要准备三个文件

  •         Udpclient.cc——用来运行起来客户端
  •         UdpServer.hpp——用来实现服务端的各种接口
  •         main.cc——用来运行起来服务端

        除了这三个主要的文件。 其实博主还准备了两个可以忽略的文件(为了方便)。 一个是博主自己写的日志程序, 用来打印日志。 一个是makefile, 方便编译。 

        如果没有日志程序的话,打印错误信息时直接cout, printf打印即可。 makefile建议带上, 方便编译养成好习惯。

实现步骤

注意, 一步到位是很难的。 所以我们先实现简单的功能, 再实现困难的功能。

        这里简单的功能就是,先让客户端能够将数据发给服务端了, 然后服务端接收到消息后再将数据返回给客户端。

        这里困难的功能就是当多个客户端如何看到互相的信息。然后如何能够一遍发信息,一边收信息。 

实现服务端客户端的收发消息

Udpserver

        实现逻辑:Udpserver.hpp中封装一个类。这个类里面封装一些接口, 然后我们在main函数中创建类对象, 在执行接口操作。

        所以, 先封装一个类, 将要实现的接口以及要用到的变量写上, 实现一个框架:

#include<iostream>
using namespace std;
#include<string>

int defaultport = 8080;       //默认的端口号,我们要创建一个默认的端口号
string defaultip = "0.0.0.0"; //在服务器中使用套接字的时候, bind函数不能绑定公网IP, 因为
//服务器的公网IP可能是虚拟的, 注意,IP地址是和网卡挂钩的, 一个网卡只能有一个IP地址。 
//绑定ip地址就是说在绑定网卡,也就是说绑定某个IP地址后就只能监听这一个网卡的消息了。 但是
//有些机器是有很多张网卡的, 所以就有一个默认IP:0.0.0.0, 绑定这个IP就能监听在本机器下面
//所有的网卡的信息。 


Log lg;

class UdpServer
{
public:
    UdpServer(uint16_t port = defaultport) 
        : port_(port), ip_(defaultip), isrunning_(false)
    {}

    void Init()
    {

    }


    void run(func_t func)
    {

    }

    ~UdpServer()
    {

    }
private:
    int sockfd_;     //服务端的网卡文件的编号
    uint16_t port_;  //服务器起来后的端口号
    string ip_;      //服务器起来的时候所在的ip地址
    bool isrunning_; //服务器是否正在运行


};

        下面是main.cpp里面的内容, 直接启动服务端。 

#include"UdpServer.hpp"
#include<memory>



int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        cout << "has return" << endl;
        return 1;
    }
    //
    uint16_t serverport = stoi(argv[1]);  

    unique_ptr<UdpServer> svr(new UdpServer(serverport));
    //
    svr->Init();
    svr->run();


    return 0;
}

Init函数

        Udpserver里面的Init函数, 这个函数用来绑定服务端的套接字的。 什么是绑定? 博主目前的理解就是将我们运行的服务端这个程序能够和网卡建立起关系。         

        这个关系中, 关系的两端是我们运行的服务端程序和socket网卡文件(网卡文件就代表了网卡)。关系的纽带是ip地址和端口号。 利用ip地址和端口号来将我们的服务端程序绑定给网卡, 这个时候因为网卡的工作性质, 其他的进程都不能再绑定网卡了, 直到我们的服务端退出。 

    void Init()
    {
        //先创建套接字变量并且完成初始化。 然后就创建网卡文件
        sockaddr_in local;
        
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        local.sin_addr.s_addr = inet_addr(ip_.c_str());
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd_ < 0)
        {
            lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));
            exit(SockError);
        }
        lg(Info, "create sock success");
        
        //绑定
        if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) 
        {
            lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));
            exit(BindError);
        }
        lg(Info, "bind success");
    }

run函数 

        我们这里思考一个问题, 我们要实现的其实是服务端与客户端之间收发消息。 所以, 我们就要客户端先发, 然后服务端收消息。 

        然后! 服务端收到消息将消息 处理一下 再将消息发回客户端。

        所以,这个过程中服务端有三个主要的动作, 一个是收,一个是处理, 一个是发。         

        然后我们的处理怎么处理, 我们可以将处理动作暴露出去,  交给main.cpp来决定。 ——利用回调函数, main.cpp中将要执行的动作作为函数传给run函数。 

如下为接口:

    //这里的func_t是一个回调函数的类型。 什么类型, 使用包装器包装的!注意
    //包含头文件functional
    using func_t = function<string(string)>; 


    void run(func_t func)
    {
        isrunning_ = true;
        char inbuffer[1024];


        while (isrunning_)
        {
            memset(inbuffer, 0, sizeof(inbuffer));
            sockaddr_in client;
            socklen_t client_len;
            memset(&client, 0, sizeof(client));
            //接收数据的同时监听到客户端的来源
            ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);
            if (s < 0) 
            {
                lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));
                continue;
            }
            inbuffer[s] = 0;

            //处理数据
            //创建套接字, 用来监听是哪一个客户端

            string message = inbuffer;
            message = func(message);//这里的处理使用一个外部的接口

            //处理完成后, 返回发送给客户端

            sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&client, sizeof(client));


        }
    }

 UdpServer析构

析构函数不解释

    ~UdpServer()
    {
        if (sockfd_ > 0) close(sockfd_);    
    }

Udpclient

        客户端就是给对应的服务端发送数据。 数据被服务端处理后接收即可:

#include<iostream>
#include<cstdlib>
#include<unistd.h>
using namespace std;
#include<sys/types.h>
#include<strings.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<string>



//./udpclient serverip serverport 
int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        cout << "has return" << endl;
        return 1;
    }
    //
    string serverip = argv[1];
    uint16_t serverprot = stoi(argv[2]);
    
    //创建套接字
    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverprot);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());
    socklen_t serlen = sizeof(server);

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        cout << "socker error" << endl; 
        return 1;
    }


    string message;
    char buffer[1024];
    while(true)
    {   

        cout << "please Enter@:" << endl;
        getline(cin, message);  
        
        //发送数据
        sendto(sockfd, message.c_str(), message.size(), 0,  (struct sockaddr*)&server, serlen);
        cout << "yes" << endl;

        //接收数据
        sockaddr_in temp;
        socklen_t socklen;
        ssize_t sz = recvfrom(sockfd, (void*)buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &socklen); //sockfd其实就是网卡的pid
        
        if(sz > 0)
        {
            buffer[sz] = 0;
            cout << buffer << endl;
        }
    }
    

    close(sockfd);
    return 0;
}

实现客户端之间的聊天功能

Udpserver

        实现客户端之间的聊天可是说是在上面的代码中改两个地方。 一个是创建一个哈希表存储有多少客户端连接了服务端。 然后以后发消息就直接便利整个哈希表, 然后将数据发给每一个客户端。 如下:

#include<iostream>
using namespace std;
#include<sys/types.h>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include"Log.hpp"
#include<functional>
#include<netinet/in.h>
#include<unordered_map>


int defaultport = 8080;
string defaultip = "0.0.0.0";

//包装类要进行修改一下
using func_t = function<string(string, sockaddr_in&, unordered_map<string, sockaddr_in>&)>; 

Log lg;

enum
{
    SockError = 2,
    BindError = 3,
    RecvError = 4,
};

class UdpServer
{
public:
    UdpServer(uint16_t port = defaultport) 
        : port_(port), ip_(defaultip), isrunning_(false)
    {}
    
    //Init不变
    void Init()
    {
        //先创建套接字变量并且完成初始化。 然后就创建网卡文件
        sockaddr_in local;
        
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        local.sin_addr.s_addr = inet_addr(ip_.c_str());
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd_ < 0)
        {
            lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));
            exit(SockError);
        }
        lg(Info, "create sock success");
        
        //绑定
        if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) 
        {
            lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));
            exit(BindError);
        }
        lg(Info, "bind success");
    }
    

    //遍历哈希表,将数据分发给所有的客户端
    void BroadCast(string message, unordered_map<string, sockaddr_in>& clients)
    {
        cout << "1 "<< endl;
        for (auto& e : clients)
        {
            sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&e.second, sizeof(e.second));
        }
        cout << "2 " << endl;
    }

    
    void run(func_t func)
    {
        isrunning_ = true;
        char inbuffer[1024];


        while (isrunning_)
        {
            memset(inbuffer, 0, sizeof(inbuffer));
            sockaddr_in client;
            socklen_t client_len;
            memset(&client, 0, sizeof(client));
            //接收数据的同时监听到客户端的来源
            ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);
            if (s < 0) 
            {
                lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));
                continue;
            }
            inbuffer[s] = 0;

            //处理数据
            //创建套接字, 用来监听是哪一个客户端

            string message = inbuffer;
            message = func(message, client, clients);//这里的处理使用一个外部的接口

            //处理完成后, 返回发送给客户端
            BroadCast(message, clients);

        }
    }

    ~UdpServer()
    {
        if (sockfd_ > 0) close(sockfd_);    
    }
private:
    int sockfd_;
    uint16_t port_;
    string ip_;
    bool isrunning_;
    unordered_map<string, sockaddr_in> clients; //添加哈希表

};

#include"UdpServer.hpp"
#include<memory>

//main.cc主要修改就是Handler函数, 我们要通过client里面的ip地址和端口号作为key,client作为value,然后放入哈希表。 同时将message处理一下,方便我们观看结果。 
string Handler(string message, sockaddr_in& client, unordered_map<string, sockaddr_in>& clients)
{
    string tmp = inet_ntoa(client.sin_addr) + to_string(client.sin_port);
    if (!clients.count(tmp))
    {
        clients[tmp] = client; 
        cout << "ip " << inet_ntoa(client.sin_addr) << " : port " << client.sin_port << " has add in talk room" << endl;
    }
    message = "[" + string(inet_ntoa(client.sin_addr)) + ":" + to_string(client.sin_port) + "]#: " + message; 
    return message;
}

// 

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        cout << "has return" << endl;
        return 1;
    }
    //
    uint16_t serverport = stoi(argv[1]);  

    unique_ptr<UdpServer> svr(new UdpServer(serverport));
    //
    svr->Init();
    svr->run(Handler);


    return 0;
}

Udpclient

#include<iostream>
using namespace std;
#include<string>
#include<sys/types.h>
#include"Log.hpp"
#include<sys/socket.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>
#include<netinet/in.h>
Log lg;


class ThreadData
{
public:
    sockaddr_in server;
    int sockfd;
};

//数据接收函数
void* recv_message(void* args)
{
    char buffer[1024];
    ThreadData* td = static_cast<ThreadData*>(args);    
    while (true)
    {
        //接收数据
        sockaddr_in temp;
        socklen_t len;
        string info;
        ssize_t s = recvfrom(td->sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &len);

        if (s < 0)
        {
            lg(Error, "recv error, error: %d, strerror: %s", errno, strerror(errno));
            continue;
        }
        buffer[s] = 0;
        info = buffer;
        cout << info << endl;
    }

}

//数据发送函数
void* send_message(void* args)
{
    ThreadData* td = static_cast<ThreadData*>(args);
    string message;
    while (true)
    {  
        getline(cin, message);  //获取数据
        //发送数据
        sendto(td->sockfd, message.c_str(), message.size(), 0, (sockaddr*)&td->server, sizeof(td->server));

    }
}

int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        cout << "Client server" << endl;
    }

    //先拿到套接字的参数
    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    ThreadData td;

    //创建套接字与打开网卡
    memset(&td.server, 0, sizeof(td.server));
    td.server.sin_family = AF_INET;
    td.server.sin_port = htons(serverport);
    td.server.sin_addr.s_addr = inet_addr(serverip.c_str());
    td.sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建文件描述符, 网卡的文件描述符, 网络传输就是使用网络文件描述符找到对应的文件内的数据
    if (td.sockfd < 0)
    {
        lg(Error, "client create sockfd error, errno: %d, strerror: %s", errno, strerror(errno));
        exit(1);
    }

    

    //创建线程, 然后运行线程, 等待线程
    pthread_t recv, send;
    pthread_create(&recv, nullptr, recv_message, &td);
    pthread_create(&send, nullptr, send_message, &td);

    pthread_join(recv, nullptr);
    pthread_join(send, nullptr);

    close(td.sockfd);
    return 0;
}

运行结果

最后就是运行结果, 运行结果就是下图了, 我们已经能够成功的进行两个客户端之间的远程交流

 ——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!! 

标签:UDP,socket,errno,linux,sockfd,UdpServer,include,local,服务端
From: https://blog.csdn.net/strive_mianyang/article/details/143349238

相关文章

  • 【最新】Kali Linux虚拟机安装与优化全攻略:必做设置让你事半功倍!
    内容预览≧∀≦ゞ【干货】KaliLinux虚拟机安装与优化全攻略简介一、从清华镜像源下载KaliLinux镜像二、配置虚拟机硬件设置三、切换KaliLinux的软件源四、解决KaliLinux与Windows之间的复制粘贴互通问题五、Kali终端优化1.调整终端窗口大小、字体大小及光标样式2.......
  • 最新宝塔安装教程:Linux 稳定版 9.0 宝塔面板+免费SSL证书解析
    在本教程中,我们将详细介绍如何在Linux服务器上安装宝塔面板的最新稳定版9.0,并为您的网站添加免费的SSL证书。此教程适合初学者和有一定经验的用户。通过SSH连接至VPS服务器后,您将能够顺利完成宝塔安装和初步设置,这篇文章将为您提供简单易懂的操作指南,帮助您在几分钟内完成服务......
  • Linux基本指令(一)
    01ls指令语法:ls[选项][目录或文件]功能:罗列当前目录下的指定文件或目录常见选项-a(显示当前目录下的所有文件) -l(显示文件详情) -d(不进入文件里面)示例:ls-a ls-l ls-a-l(命令中的选项可以传递多个)以“.”开头的为隐藏文件,在加上-a后才可见  文件=......
  • 最新宝塔安装教程:Linux 稳定版 9.0 宝塔面板+免费SSL证书解析
    在本教程中,我们将详细介绍如何在Linux服务器上安装宝塔面板的最新稳定版9.0,并为您的网站添加免费的SSL证书。此教程适合初学者和有一定经验的用户。通过SSH连接至VPS服务器后,您将能够顺利完成宝塔安装和初步设置,这篇文章将为您提供简单易懂的操作指南,帮助您在几分钟内完成服务......
  • Grafana Nginx 403 Origin not allowed 及 ws websocket连接错误解决
    GrafanaNginx403Originnotallowed及wswebsocket错误解决---我超怕的https://www.cnblogs.com/iAmSoScArEd/p/18514291注意,这里日志并不全,仅贴了关键解决问题的部分,请勿直接复制粘贴用于生产环境。http{#解决websocket错误https://nginx.org/en/docs/http/we......
  • 【Linux操作系统】Linux配置OpenSSH服务器步骤记录
    1.安装OpenSSH服务器软件包用指令查询,已经全部安装。编辑/etc/ssh/sshd_config文件:#      $OpenBSD:sshd_config,v1.1032018/04/0920:41:22tjExp$#Thisisthesshdserversystem-wideconfigurationfile. See#sshd_config(5)formoreinformat......
  • 如何在Linux上配置软件负载均衡(如HAProxy)
    在Linux环境中,确保应用服务的高可用性和性能是至关重要的。本文将引导你完成以下步骤:1.理解软件负载均衡的重要性;2.选择合适的负载均衡器;3.详细配置HAProxy为例;4.进行性能调优和测试;5.监控和维护。开始负载均衡配置之前,首先需要明确其作用和目标。1.理解软件负载均衡的重要性......
  • 安装配置rocky Linux 9.4的环境
    安装RockyLinux9.4系统:由于centos7已经停止技术支持,作为代替的技术选型探索,选用centos创始人发起的rockylinux作为平替进行测试验证。1.在虚拟机中安装完系统后,首先替换阿里云源,但是出现了SSL的报错。所以正确的配置顺序应该是确保系统的ca-certificates软件包是最新的,这......
  • linux 命令值xargs与tr
    提出问题:为什么有了管道符|,还需要xagrs管道符 | 允许将一个命令的输出作为另一个命令的输入。然而,管道符在处理某些类型的输入时存在局限性,特别是当需要将一系列输入项作为单个命令的多个参数时()。xargs 的出现正是为了解决这个问题。xargs 能够从标准输入(stdin)读取数据,......
  • Linux压缩和解压文件
    1.linux压缩文件到指定文件夹方法一:使用tar命令压缩文件tar-czvf/目标文件夹/压缩文件名.tar.gz/要压缩的文件或文件夹路径这将把指定的文件或文件夹压缩为一个名为“压缩文件名.tar.gz”的gzip压缩文件,并将该文件保存到指定的目标文件夹。方法二:使用zip命令压缩文件zip......