【Linux】网络编程 - Socket套接字/基于UDP的网络通信

2023-11-19

目录

一.套接字

1.什么是套接字/Socket套接字

2.套接字的分类

3.Socket套接字的常见API

二.网络字节序

1.什么是网络字节序

2.网络字节序和主机字节序的转换接口

三.IP地址形式上的转换

四.客户端的套接字不由程序员bind

1.为什么客户端套接字不能由程序员bind

2.OS是在什么时候给客户端bind了ip和port

五.基于UDP的网络通信

1.传输层协议UDP的基本特性

2.基于UDP协议的C/S网络通信

1).demo代码1

2.demo代码2 - mini聊天室

六.补充扩展

1.本地环回ip地址

2.云服务器不能绑定指定IP地址

3.服务器不推荐绑定确定IP


一.套接字

1.什么是套接字/Socket套接字

套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序),各种进程使用这个相同的域互相之间用Internet协议簇来进行通信

Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连进程。通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 Socket中,该 Socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另外一台主机的 Socket中,使对方能够接收到这段信息。 Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制

                                                                                                                                                                                                --- 摘自百度

Socket套接字属于应用层和传输层协议之间的一个抽象层, Socket套接字系列的API都是传输层来提供给我们使用的接口, 用来让我们在应用层中编写网络编程代码

在linux中, 一切皆文件, 网卡也是文件; socket套接字, 本质上, 就是一个文件描述符fd, 因为网络通信的本质也是使用文件来进行通信, 创建好套接字, 之后的网络通信, 想要发送/接收信息数据本质上都是在利用这个套接字文件来进行

2.套接字的分类

域间套接字 - 用于本主机内的进程间通信 - 基于套接字式的管道通信 - 原理类似于命名管道通信

原始套接字 - 用来编写一些工具 - 可以绕过运输层或网络层或其他层直接使用底层

网络套接字 - 用于网络通信 - 例如, socket套接字就是网络套接字

以上, 理论上应该是三套接口, 而linux"封装"了套接字类型, 将所有的接口进行了统一

其统一就体现在, sockaddr结构体类型

不管是sockaddr_in还是sockaddr_un都可以以强制类型转换的方式传给sockaddr, sockaddr依靠前两字节判断该sockaddr具体是sockaddr_in还是sockaddr_un还是其他套接字..., 补充: 为何不用void*? 因为网络接口的设计比C语言中void*更早, 所以那时还没有void*

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

以上三个头文件, 有一些网络编程中常用函数和sockaddr_in类型所需

sockaddr_in网络通信结构体类型: 

 

总之, struct sockaddr_in内需要有:

哪种套接字(sin_family 类型: AF_INET or AF_UNIX or AF_LOCAL ...宏 --> int)

IP地址(sin_addr 类型: struct in_addr --> 内部只有一个成员s_addr 类型: in_addr_t --> uint32_t)

Port端口(sin_port 类型: in_port_t --> uint16_t)

剩下的均为填充字段(sin_zero不用管)

3.Socket套接字的常见API

#include <sys/types.h>

#include <sys/socket.h>

创建socket套接字, 即文件描述符(TCP/UDP)

本质: 创建一个指明运输层协议的文件供我们用来网络通信

int socket(int domain, int type, int protocol);

参数

1.domain: 表示套接字的域, 即套接字的类型, AF_UNIX域AF_LOCAL用于本地通信, AF_INET和AF_INET6用于网络通信(IPv4和IPv6), ...

2.type: 类型, 你想创建这个套接字的通信种类是什么, 面向流SOCK_STREAM?or面向数据报SOCK_DGRAM?or other?

3.protocol: 协议, 你想使用哪一种协议, 通常第一二个参数填好, 就代表第三个参数填好了, 如用AF_INET且SOCK_DGRAM也就代表使用传输层的UDP协议, 或AF_INET且SOCK_STREAM也就代表使用传输层的TCP协议, 通常如果采用默认传0即可

返回值: 文件描述符(在网络中就是套接字)

绑定端口号(TCP/UDP)

本质: 将用户设置的IP和port在内核中和我们当前进程及创建的socket套接字强关联

int bind(int socket, const struct sockaddr *addr, socklen_t address_len);

参数

1.socket: 我们创建的套接字

2.addr: 填充ip和port的结构体, 需要将struct sockaddr_in*强转成struct sockaddr*

3.address_len: addr结构体的长度(本质: uint32_t)

返回值: 成功返回0, 否则返回-1, 设置错误码errno

开始监听socket(TCP)

int listen(int socket, int backlog);

接收请求(TCP)

int accept(int socket, struct sockaddr *addr, socklen_t *address_len);

建立连接(TCP)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

ssize_t recv(int sockfd, void* buf, size_t len, int flags);

ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)

本质: 从源ip主机, 即网络中, 接收数据

参数

sockfd: 创建并且绑定的套接字

buf: 读到buf中

len: buf大小

flags: 读取方式, 0代表阻塞式读取

src_addr: 源IP和port, 输出型参数

addrlen: 源IP和port的长度, 输入输出型参数, 输入: struct sockaddr_in的大小 输出: 实际读到的src_addr大小

注:!! src_addr与addrlen本质是要获取, 发送数据一端的ip&&port信息

返回值: 实际读取到的字节个数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

本质: 向目的ip主机, 即网络中, 发送数据

参数

sockfd: 创建并且绑定的套接字

buf: 发送数据的内容

len: 发送数据的长度

flags: 读取方式, 0代表阻塞式读取

dest_addr: 目的端的信息, ip port family...

addrlen: dest_addr的长度

二.网络字节序

1.什么是网络字节序

在计算机中, 内存存储字节有两种方式: 大端或小端

一台主机发送给另一台主机数据, 这两台机器在网络通信时并不知道对方是大端机还是小端机, 为了能够统一字节序, 便有了网络字节序这一概念

在TCP/IP协议族中, 网络字节序采用大端, 也就是不管发送什么数据, 都会按照大端(网络字节序)来发送/接收数据, 如果当前发送机是小端, 就要先将数据转成大端; 否则就忽略, 直接发送即可; 从网络中接收数据时也是同理

2.网络字节序和主机字节序的转换接口

包含头文件 <arpa/inet.h>

主机转网络

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

网络转主机

uint32_t ntohl(uint16_t netlong);

uint16_t ntohs(uint16_t netshort);

注: h - host代表主机; n - network代表网络; l - long代表长整型; s - short代表短整型

通常如果是port, 用short - uint16_t; 如果是IP, 用long - uint32_t

三.IP地址形式上的转换

为了让人更方便的看到ip地址, 通常输出/输入"点分十进制" 的ip地址, 每个.之间的数取值范围[0, 255]因为一个数只占1字节, 实际上计算机存储ip地址只需要4Byte就够了, 要是通过网络的传输的话还要把4字节ip转换为网络字节序, 这样一共有两步转换

1."点分十进制"字符串式ip --> 主机序列的4字节ip

2.主机序列的4字节ip --> 网络序列的4字节ip

以上两步可以通过同一接口进行转换

"点分十进制"字符串式ip --> 网络序列的4字节ip: in_addr_t inet_addr(const char* cp);

网络序列的4字节ip --> "点分十进制"字符串式ip: char *inet_ntoa(struct in_addr in);

四.客户端的套接字不由程序员bind

1.为什么客户端套接字不能由程序员bind

客户端client一定需要绑定ip和端口, 但是由用户的OS自动绑定的, 不能由程序员手动绑定, 因为程序员写的客户端client在未来是要交给用户, 并且让用户下载的, 程序员并不知道在用户的机器上的端口的使用情况, 由于1个端口只能绑定一个客户端, 所以这个绑定的过程要交给用户的机器OS自动进行

2.OS是在什么时候给客户端bind了ip和port

当客户端client首次发送信息给服务器的时候, 用户的OS会自动给用户客户端client绑定它的ip和port

五.基于UDP的网络通信

1.传输层协议UDP的基本特性

有连接

可靠传输

面向字节流

2.基于UDP协议的C/S网络通信

1).demo代码1

udp_server.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <strings.h>
#include <unistd.h>
#include <cstring>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpServer
{
public:
    udpServer(const uint16_t port, const std::string ip = "") : _port(port), _ip(ip)
    {
    }
    void Init()
    {
        // 1.创建Socket套接字
        _socket = socket(AF_INET, SOCK_DGRAM, 0);
        assert(_socket != -1);
        std::cout << "创建Socket套接字成功" << std::endl;

        // 2.绑定Socket套接字 -- ip和port
        struct sockaddr_in sv;
        bzero(&sv, sizeof(sv));
        sv.sin_family = AF_INET;
        sv.sin_port = htons(_port);
        sv.sin_addr.s_addr = _ip == "" ? INADDR_ANY : inet_addr(_ip.c_str());
        socklen_t len = sizeof(sv);

        int ret = bind(_socket, (struct sockaddr *)&sv, len);
        assert(ret != -1);
        std::cout << "绑定Socket套接字成功" << std::endl;
    }
    void Start()
    {
        while (true)
        {
            // 3.开始通信
            char buffer[1024];
            bzero(buffer, sizeof(buffer));
            // 3.1接收数据
            struct sockaddr_in cli;
            bzero(&cli, sizeof(cli));
            socklen_t len = sizeof(cli);

            ssize_t n = recvfrom(_socket, buffer, sizeof(buffer), 0, (struct sockaddr *)&cli, &len);
            if (n > 0)
            {
                buffer[n] = '\0';
                // 3.2输出读取数据
                std::string cli_ip = inet_ntoa(cli.sin_addr);
                uint16_t cli_port = ntohs(cli.sin_port);
                printf("[%s:%d]# %s\n", cli_ip.c_str(), cli_port, buffer);

                // 4.原路发回
                sendto(_socket, buffer, strlen(buffer), 0, (struct sockaddr*)&cli, len);
            }
            else
            {
                std::cout << "本次未读到数据" << std::endl;
            }
        }
    }
    ~udpServer()
    {
        close(_socket);
    }

private:
    uint16_t _port;   // 端口
    std::string _ip;  // ip
    int _socket = -1; // Socket套接字
};

udp_server.cc

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


static inline void Usage(char *&proc)
{
    std::cout << "correct way to use: " << proc << " port" << std::endl;
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(-1);
    }

    uint16_t server_port = atoi(argv[1]); 

    std::unique_ptr<udpServer> server(new udpServer(server_port));

    // 初始化服务器
    server->Init();

    // 启动服务器
    server->Start();

    return 0;
}

client.cc

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


static inline void Usage(char *&proc)
{
    std::cout << "correct way to use: " << proc << " port" << std::endl;
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(-1);
    }

    uint16_t server_port = atoi(argv[1]); 

    std::unique_ptr<udpServer> server(new udpServer(server_port));

    // 初始化服务器
    server->Init();

    // 启动服务器
    server->Start();

    return 0;
}

2.demo代码2 - mini聊天室

udp_server.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <strings.h>
#include <unistd.h>
#include <cstring>
#include <unordered_map>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpServer
{
public:
    udpServer(const uint16_t port, const std::string ip = "") : _port(port), _ip(ip)
    {
    }
    void Init()
    {
        // 1.创建Socket套接字
        _socket = socket(AF_INET, SOCK_DGRAM, 0);
        assert(_socket != -1);
        std::cout << "创建Socket套接字成功" << std::endl;

        // 2.绑定Socket套接字 -- ip和port
        struct sockaddr_in sv;
        bzero(&sv, sizeof(sv));
        sv.sin_family = AF_INET;
        sv.sin_port = htons(_port);
        sv.sin_addr.s_addr = _ip == "" ? INADDR_ANY : inet_addr(_ip.c_str());
        socklen_t len = sizeof(sv);

        int ret = bind(_socket, (struct sockaddr *)&sv, len);
        assert(ret != -1);
        std::cout << "绑定Socket套接字成功" << std::endl;
    }
    void Start()
    {
        while (true)
        {
            // 3.开始通信
            char buffer[1024];
            bzero(buffer, sizeof(buffer));
            // 3.1接收数据
            struct sockaddr_in cli;
            bzero(&cli, sizeof(cli));
            socklen_t len = sizeof(cli);

            ssize_t n = recvfrom(_socket, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&cli, &len);

            char key[64];
            bzero(key, sizeof(key));
            if (n > 0)
            {
                buffer[n] = '\0';

                // 3.2输出读取数据

                std::string cli_ip = inet_ntoa(cli.sin_addr);
                uint16_t cli_port = ntohs(cli.sin_port);

                printf("[%s:%d]# %s\n", cli_ip.c_str(), cli_port, buffer); // 给服务器打印

                // 注册发送数据的用户信息
                snprintf(key, sizeof(key), "%s-%u", cli_ip.c_str(), cli_port);

                _usrmessage[key] = cli;
            }

            // 向所有注册过的用户广播信息
            std::string message;
            message += key;
            message += "#";
            message += buffer;
            message += "\n";
            
            for (auto &e : _usrmessage)
            {
                std::cout << "广播............" << std::endl;
                // 4.原路发回
                sendto(_socket, message.c_str(), message.size(), 0, (struct sockaddr *)&(e.second), sizeof(e.second));
            }
        }
    }
    ~udpServer()
    {
        close(_socket);
    }

private:
    uint16_t _port;   // 端口
    std::string _ip;  // ip
    int _socket = -1; // Socket套接字

    std::unordered_map<std::string, struct sockaddr_in> _usrmessage;
};

udp_server.cc

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


static inline void Usage(char *&proc)
{
    std::cout << "correct way to use: " << proc << " port" << std::endl;
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(-1);
    }

    uint16_t server_port = atoi(argv[1]); 

    std::unique_ptr<udpServer> server(new udpServer(server_port));

    // 初始化服务器
    server->Init();

    // 启动服务器
    server->Start();

    return 0;
}

udp_client.hpp

#pragma once

#include <iostream>
#include <cstdlib>
#include <strings.h>
#include <memory>
#include <unistd.h>
#include <thread>
#include <cstdio>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpClient
{
private:
    static void Send(struct sockaddr_in sendUsr, int sock)
    {
        while (true)
        {
            // 2.发送数据
            std::string sendmessage;
            std::cout << "请输入: ";
            std::getline(std::cin, sendmessage);

            sendto(sock, sendmessage.c_str(), sendmessage.size(), 0, (struct sockaddr *)&sendUsr, sizeof(sendUsr));

            if (sendmessage == "quit")
            {
                std::cout << "the clientSend is closed" << std::endl;
                break;
            }
        }
    }

    static void Recv(int sock)
    {
        std::string namedPath = "./JOKER.txt";
        umask(0);
        mkfifo(namedPath.c_str(), 0666);

        int fd = open(namedPath.c_str(), O_WRONLY | O_APPEND);

        while (true)
        {
            // 3.接收server echo
            char buffer[1024];
            bzero(buffer, sizeof(buffer));
            ssize_t n = recv(sock, buffer, sizeof(buffer), 0);
            if (n > 0)
            {
                buffer[n] = '\0';

                //std::cout << "Server Echo# " << buffer << std::endl;
                write(fd, buffer, sizeof(buffer));

                if (buffer == "quit")
                {
                    std::cout << "the clientRecv is closed" << std::endl;
                    break;
                }
            }
        }
        close(fd);
    }

public:
    udpClient(std::string sip, uint16_t sport) : _sv_ip(sip), _sv_port(sport), _socket(-1)
    {
    }

    void Init()
    {
        // 1.创建套接字
        _socket = socket(AF_INET, SOCK_DGRAM, 0);

        // 客户端由客户机OS自动绑定
    }

    void Start()
    {
        struct sockaddr_in sendUsr;
        bzero(&sendUsr, sizeof(sendUsr));

        sendUsr.sin_family = AF_INET;
        sendUsr.sin_addr.s_addr = inet_addr(_sv_ip.c_str());
        sendUsr.sin_port = htons(_sv_port);

        std::thread t_send(Send, sendUsr, _socket);
        std::thread t_recv(Recv, _socket);

        t_send.join();
        t_recv.join();
    }

    ~udpClient()
    {
        close(_socket);
    }

private:
    std::string _sv_ip;
    uint16_t _sv_port;

    int _socket;
};

udp_client.cc 

#include "udp_client.hpp"

static inline void Usage(char *&proc)
{
    std::cout << "correct way to use: " << proc << " ip port" << std::endl;
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(-1);
    }

    std::string sv_ip = argv[1];
    uint16_t sv_port = atoi(argv[2]);

    std::unique_ptr<udpClient> client(new udpClient(sv_ip, sv_port));

    client->Init();

    client->Start();

    return 0;
}

六.补充扩展

1.本地环回ip地址

ip地址: 127.0.0.1 --> 本地环回

client和server发送数据指在本地协议栈中进行数据流动, 不会把我们的数据发送到网络中

只是把TCP/IP五层协议栈走一遍, 通常用来做本地网络服务器的测试

2.云服务器不能绑定指定IP地址

云服务器无法绑定公网IP地址

在云服务器中, 比如腾讯云, 他给我们提供的IP地址全部都是虚拟出来的, 不允许绑定这个确定的ip地址, 实际使用的不是这个IP地址, 所以我们无法在服务器进程上直接绑定这个地址

但其他人是可以通过这个虚拟出来的ip向云服务器互相网络通信的, 因为可以通过服务器进程绑定任意ip地址的方式来达到

3.服务器不推荐绑定确定IP

推荐服务器绑定"任意IP" -- 使用INADDR_ANY宏

INADDR_ANY宏, 本质是(in_addr_t)0x0000 0000 -- 让服务器在工作过程中可以从任意IP中获取数据 -- 即可以理解为有多少张网卡有多少IP都可以绑定上

因为服务器也许不止一张网卡, 也许有很多张网卡, 如果绑定了具体IP地址, 则服务器只能收到发送到这个IP地址的消息, 而如果使用任意IP的绑定方法, 则服务器就能收到发送到很多个IP地址的消息, 比如该服务器有3张网卡, 则客户端有可能分别向这三张网卡的IP发送数据, 服务器就都能收到了

当在机器上查看一个服务器进程或客户端进程的IP地址为0.0.0.0就说明为任意IP地址绑定

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux】网络编程 - Socket套接字/基于UDP的网络通信 的相关文章

  • ansible 重新启动 2.1.1.0 失败

    我一直在尝试创建一个非常简单的 Ansible 剧本 它将重新启动服务器并等待它回来 我过去在 Ansible 1 9 上有一个可以运行的 但我最近升级到 2 1 1 0 并且失败了 我正在重新启动的主机名为 idm IP 为 192 16
  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • Elasticsearch 无法写入日志文件

    我想激活 elasticsearch 的日志 当我运行 elasticsearch 二进制文件时 我意识到我在日志记录方面遇到问题 无法加载配置 这是输出 sudo usr share elasticsearch bin elasticse
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 如何使用 xterm.js 创建基于 Web 的终端以 ssh 进入本地网络上的系统

    我偶然发现了这个很棒的图书馆xterm js https xtermjs org 这也是 Visual Studio Code 终端的基础 我有一个非常普遍的问题 我想通过基于网络的终端 不在网络中 可能位于 aws 服务器上 访问本地网络
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 为什么内核需要虚拟寻址?

    在Linux中 每个进程都有其虚拟地址空间 例如 32位系统为4GB 其中3GB为进程保留 1GB为内核保留 这种虚拟寻址机制有助于隔离每个进程的地址空间 对于流程来说这是可以理解的 因为有很多流程 但既然我们只有 1 个内核 那么为什么我
  • 大多数 Linux 系统头文件与 C++ 兼容吗?

    大多数 Linux 系统头文件 API C 兼容吗 今天我试图做这样的事情 include
  • 从 Python 调用 PARI/GP

    我想打电话PARI GP http pari math u bordeaux fr dochtml gpman html仅从Python计算函数nextprime n 对于不同的n是我定义的 不幸的是我无法得到帕里蟒蛇 http code
  • Linux中的定时器类

    我需要一个计时器来以相对较低的分辨率执行回调 在 Linux 中实现此类 C 计时器类的最佳方法是什么 有我可以使用的库吗 如果您在框架 Glib Qt Wx 内编写 那么您已经拥有一个具有定时回调功能的事件循环 我认为情况并非如此 如果您
  • fopen 不返回

    我在 C 程序中使用 fopen 以只读模式 r 打开文件 但就我而言 我观察到 fopen 调用没有返回 它不返回 NULL 或有效指针 执行在 fopen 调用时被阻止 文件补丁绝对正确 我已经验证过 并且不存在与权限相关的问题 任何人
  • Android 时钟滴答数 [赫兹]

    关于 proc pid stat 中应用程序的总 CPU 使用率 https stackoverflow com questions 16726779 total cpu usage of an application from proc
  • 如何在数组中存储包含双引号的命令参数?

    我有一个 Bash 脚本 它生成 存储和修改数组中的值 这些值稍后用作命令的参数 对于 MCVE 我想到了任意命令bash c echo 0 0 echo 1 1 这解释了我的问题 我将用两个参数调用我的命令 option1 without
  • arm64和armhf有什么区别?

    Raspberry Pi Type 3 具有 64 位 CPU 但其架构不是arm64 but armhf 有什么区别arm64 and armhf armhf代表 arm hard float 是给定的名称Debian 端口 https
  • Pyaudio 安装错误 - “命令‘gcc’失败,退出状态 1”

    我正在运行 Ubuntu 11 04 Python 2 7 1 并想安装 Pyaudio 于是我跑了 sudo easy install pyaudio 在终端中 进程退出并显示以下错误消息 Searching for pyaudio Re
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • 如何在shell中输出返回码?

    我正在尝试通过调用自定义 shell 脚本sh bin sh c myscript sh gt log txt 2 gt 1 echo 该命令的输出是创建的后台进程的 PID 我想指导 bin sh保存返回码myscript sh到某个文件
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少

随机推荐

  • 【Android -- UI 开发】WebView 的基本使用

    一 简介 WebView 在 Android 平台上是一个特殊的 View 基于 webkit 引擎 展现 web 页面的控件 这个类可以被用来在你的 app 中仅仅显示一张在线的网页 还可以用来开发浏览器 WebView 内部实现是采用渲
  • GitHub pages 如何搭建一个个人博客

    搭建一个 GitHub Pages 个人博客的步骤如下 在 GitHub 上创建一个名为 username github io 的仓库 其中 username 是你的 GitHub 用户名 在仓库里创建一个 index html 文件 用于
  • 刚学JavaWeb如何创建一个简单的Servlet项目(保姆级!!!)

    idea如何创建一个简单的Servlet项目 一 准备步骤 1 创建一个工程 2 添加Web application支持 3 部署Tomcat服务器 4 向服务器中添加项目 5 向项目中导入所需要的JAR包 二 编写一个简单的Servlet
  • java动态加载jar包,并运行其中的类和方法

    flink 相关 https www toutiao com article 6883793897495986691 动态加载jar包 在实际开发中经常会需要用到 尤其涉及平台和业务的关系的时候 业务逻辑部分可以独立出去交给业务方管理 业务
  • Bugku题目Reverse逆向部分wp(持续更新)

    目录 入门逆向 Easy Re 游戏过关 sign in Easy vb Next 入门逆向 题目链接 丢入DIE PEID看过 没有壳 32位 直接IDA 汇编代码直接看到 flag Re 1s S0 C0OL Easy Re 题目链接
  • 查看淘宝镜像

    win R 打开输入cmd打开 查看node是否安装输入命令 node v 安装淘宝镜像输入命令 npm install g cnpm registry https registry npm taobao org 查看淘宝镜像输入命令 np
  • 场景题

    场景题 1 场景题汇总 1 情景题 如果一个外卖配送单子要发布 现在有200个骑手都想要接这一单 如何保证只有一个骑手接到单子 2 场景题 美团首页每天会从10000个商家里面推荐50个商家置顶 每个商家有一个权值 你如何来推荐 第二天怎么
  • 用Calendar.getInstance()后,set月份被加一问题

    一 问题描述 今天查询一个bug发现了这个问题 使用Calendar 中的before 和after方法比较日期是否在范围内 实际与代码不符 我就去查明原因 首先说下这两个方法吧 日期1 before 日期2 第一个日期在第二个日期之前的意
  • 将 Google Kubernetes Engine (GKE) 上稳定扩散的启动时间缩短 4 倍

    Cloud Ace 是 Google Cloud 全球战略合作伙伴 在亚太地区 欧洲 南北美洲和非洲拥有二十多个办公室 Cloud Ace 在谷歌专业领域认证及专业知识目前排名全球第一位 并连续多次获得 Google Cloud 各类奖项
  • Flutter 安装 填坑记录

    Flutter 安装过程中遇到的问题 安装参考文档 https flutterchina club Add the flutter tool to your path 不知如何在mac中添加环境变量的解决方法参照https jingyan
  • [491]pywin32模拟鼠标键盘操作

    keybd event bVk bScan dwFlags dwExtraInfo 第一个参数 虚拟键码 键盘键码对照表见附录 第二个参数 硬件扫描码 一般设置为0即可 第三个参数 函数操作的一个标志位 如果值为KEYEVENTF EXTE
  • Unable to cast COM object of type Microsoft.Office.Interop.Excel.ApplicationClass' ...

    问题描述 这个问题产生的原因 与 office 的安装有关 参考 How to solve Unable to cast COM object of type Microsoft Office Interop Excel Applicati
  • arm鲲鹏服务器和x86区别

    华为云服务器x86计算和鲲鹏计算的区别是什么 X86和鲲鹏指的是两个系列的中央处理器架构 x86采用复杂指令集 CISC 鲲鹏采用精简指令集 RISC pc6a学习分享小白详细说明一下这2种服务器的差别 一 鲲鹏和X86处理器架构对比 1
  • R语言期末

    一 单项选择题 答题说明 每题均有 A B C D 四个备选答案 其中只有一个正确答案 将其 选出 并写在答题纸上 1 R 语言 软件 是被用于统计计算和绘图工作的一套语言和环境 是一套开源 的数据分析解决方案 最早 1995 年 是由 B
  • 代码走查(codereview)如何执行才能提升代码质量

    成功上岸 进入华为 之前花5W买的JAVA课程合集 整整420集 拿走不谢 公粮上交 手把手教学 学完即可就业 哔哩哔哩 bilibili 作为一名开发工程师 如何提升个人能力 减少bug的发生是一件非常重要的事情 它直接关系到了领导及项目
  • Cesium三维地球上添加点、线、面、文字、图标(图片)、模型等标绘

    添加标绘之前要明白一点 Cesium Entity是可以与样式化图形表示配对并定位在空间和时间上的数据对象 或者说Cesium 提供 Entity API 来绘制控件数据 所以我们添加的所有标绘都是entity Entity API简介 C
  • 【DDR3 控制器设计】(3)DDR3 的写操作设计

    写在前面 本系列为 DDR3 控制器设计总结 此系列包含 DDR3 控制器相关设计 认识 MIG 初始化 读写操作 FIFO 接口等 通过此系列的学习可以加深对 DDR3 读写时序的理解以及 FIFO 接口设计等 附上汇总博客直达链接 DD
  • 2022年数字化转型的三大基于云的驱动因素

    未来一年将标志着企业品牌 工作和生活创新的最大重置 文章来源 Venture Beat Google Cloud CTO Will Grannis 数字技术一直是并将持续是公司应对新冠疫情的背后推动力 从购物和供应链到儿童保育和工作 一切都
  • 服务器访问系统盘 数据盘,云服务器系统盘数据盘

    云服务器系统盘数据盘 内容精选 换一换 当服务器中的磁盘发生故障 或者由于人为误操作导致服务器数据丢失时 可以使用已经创建成功的备份恢复服务器 云服务器备份仅支持将服务器中的所有云硬盘作为整体进行备份和恢复 不支持对服务器中的部分云硬盘进行
  • 【Linux】网络编程 - Socket套接字/基于UDP的网络通信

    目录 一 套接字 1 什么是套接字 Socket套接字 2 套接字的分类 3 Socket套接字的常见API 二 网络字节序 1 什么是网络字节序 2 网络字节序和主机字节序的转换接口 三 IP地址形式上的转换 四 客户端的套接字不由程序员