c++ socket (3) IPv4、IPv6兼容处理
nanshan 2024-10-04 18:03 22 浏览 0 评论
IP6是大势所趋(十多年前我也是这样听说的, 哈), 所以要考虑IPv4\IPv6的兼容性.
代码示例
a、IPv6兼容IPv4,所以在服务器监听时,尽量使用IPv6.
b、客户端通过getaddrinfo 获取服务端地址
公共部分头文件(socket.h)
#ifndef __SOCKET_H__
#define __SOCKET_H__
#include <memory>
#include <string>
#include <memory.h>
#ifdef _WIN32
#include <WinSock2.h>
#include <ws2tcpip.h>
#define socket_t SOCKET
#define invalid_socket INVALID_SOCKET
#define socklen_t int
#pragma comment(lib, "ws2_32.lib")
#endif // _WIN32
#ifdef __linux__
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define socket_t int
#define invalid_socket -1
#define closesocket close
#endif
class Socket {
static bool init_socket()
{
#ifdef _WIN32
WSADATA ws;
static bool _init = (0 == WSAStartup(MAKEWORD(2, 2), &ws));
return _init;
#endif
return true;
}
public:
//创建服务器(优先使用IPv6)
static socket_t CreateServer(int port, int type = SOCK_STREAM)
{
init_socket();
struct addrinfo hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // 任何地址家族
hints.ai_socktype = type; // 任何套接字类型
hints.ai_protocol = (type == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE;
int ret = 0;
struct addrinfo* res;
if ((ret = getaddrinfo(nullptr, std::to_string(port).c_str(), &hints, &res)) != 0) {
std::cout << "err getaddrinfo:" << gai_strerror(ret) << std::endl;
return invalid_socket;
}
int reuseAddr = 1;
socket_t skt = invalid_socket;
for (struct addrinfo* p = res; p != 0; p = p->ai_next) {
if ((p->ai_family != AF_INET && p->ai_family != AF_INET6)
|| (skt != invalid_socket && p->ai_family == AF_INET)) {
continue;
}
//关闭之前的IPv4
if (skt != invalid_socket) {
closesocket(skt);
skt = invalid_socket;
}
//创建socket 及 bind
if (invalid_socket == (skt = socket(p->ai_family, p->ai_socktype, p->ai_protocol))
|| 0 != setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseAddr, sizeof(int))
|| 0 != bind(skt, (const struct sockaddr*)p->ai_addr, p->ai_addrlen)) {
if (skt != invalid_socket) {
closesocket(skt);
skt = invalid_socket;
}
continue;
}
//如果是IPv6,就不必再继续了
if (skt != invalid_socket && p->ai_family == AF_INET6) {
break;
}
}
freeaddrinfo(res);
return skt;
}
//连接服务端
static socket_t ConnectServer(const char* addr, int port)
{
init_socket();
struct addrinfo hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int ret = 0;
struct addrinfo* res;
if ((ret = getaddrinfo(addr, std::to_string(port).c_str(), &hints, &res)) != 0) {
std::cerr << "getaddrinfo:" << gai_strerror(ret) << std::endl;
return invalid_socket;
}
int reuseAddr = 1;
socket_t skt = invalid_socket;
for (struct addrinfo* p = res; p != 0 && skt == invalid_socket; p = p->ai_next) {
if ((p->ai_family != AF_INET && p->ai_family != AF_INET6)) {
continue;
}
//创建socket 及 connect
if (invalid_socket != (skt = socket(p->ai_family, p->ai_socktype, p->ai_protocol))
&& 0 != connect(skt, (const struct sockaddr*)p->ai_addr, p->ai_addrlen)) {
std::cerr << "connect:" << strerror(errno);
closesocket(skt);
skt = invalid_socket;
}
}
freeaddrinfo(res);
return skt;
}
};
#endif
服务器
int main()
{
socket_t skt;
if (invalid_socket == (skt = Socket::CreateServer(80))) {
std::cerr << "CreateServer : " << strerror(errno) << std::endl;
return 0;
}
if (0 != listen(skt, 255)) {
return 0;
}
char addr[128] = { 0 };
socklen_t addrLen = 28;
socket_t client = accept(skt, (struct sockaddr*)addr, &addrLen);
//获取对端地址
char node[128] = { 0 };
char port[32] = { 0 };
if (0 == getnameinfo((const sockaddr*)addr, addrLen, node, 128, port, 32, 0)) {
if (0 == memcmp(node, "::ffff:", strlen("::ffff:"))) {
std::cout << "IPv4 connect : " << node + strlen("::ffff:") << " : " << port << std::endl;
}
else {
std::cout << "IPv6 connect :" << node << " : " << port << std::endl;
}
}
//.....
closesocket(client);
closesocket(skt);
return 0;
}
客户端
int main()
{
socket_t skt;
if (invalid_socket != (skt = Socket::ConnectServer("www.baidu.com", 80))) {
std::cout << "connect www.baidu.com ok" << std::endl;
closesocket(skt);
}
if (invalid_socket != (skt = Socket::ConnectServer("learn.microsoft.com", 80))) {
std::cout << "connect learn.microsoft.com ok" << std::endl;
closesocket(skt);
}
if (invalid_socket != (skt = Socket::ConnectServer("fe80::53bd:b44a:cf4a:d202", 80))) {
std::cout << "connect fe80::53bd:b44a:cf4a:d202 ok" << std::endl;
closesocket(skt);
}
if (invalid_socket != (skt = Socket::ConnectServer("192.168.1.21", 80))) {
std::cout << "connect 192.168.1.21 ok" << std::endl;
closesocket(skt);
}
return 0;
}
文心一言代码解析:
init_socket()函数: 这个函数是用来初始化套接字库的。
如果代码在Windows平台上运行(通过#ifdef _WIN32判断),它将调用WSAStartup()函数来初始化Windows套接字库,并检查是否成功初始化。如果成功,返回true;否则返回false。在其他平台上,这个函数总是返回true。
CreateServer()函数: 这个函数尝试创建一个服务器套接字并绑定到指定的端口。函数的参数包括端口号和套接字类型(默认为SOCK_STREAM,即TCP)。
- 首先,它调用init_socket()来初始化套接字库。
- 然后,它使用getaddrinfo()函数来获取与给定端口和地址家族相关的地址信息。这个函数返回一个地址信息链表,包含了所有可能的地址(IPv4和IPv6)。
- 接着,函数遍历这个地址链表,尝试为每个地址创建一个套接字并绑定它。如果成功,它会关闭之前创建的所有套接字(如果有的话),然后继续处理下一个地址。
- 如果成功创建了套接字并绑定了某个地址,并且这个地址是IPv6地址,那么函数会停止处理其他地址,并返回创建的套接字。
- 最后,无论成功与否,都会使用freeaddrinfo()函数释放之前获取的地址信息。 CreateServer主要目的是为了确保服务器套接字优先使用IPv6地址。如果系统支持IPv6,并且可以绑定到IPv6地址,那么它就会停止处理其他地址并返回套接字。否则,它将尝试使用IPv4地址。这有助于确保应用程序可以同时支持IPv4和IPv6,从而提供更好的网络连接性。
ConnectServer(): 这个函数用于连接到服务器。
- 它首先调用init_socket()来初始化套接字库。然后,它使用getaddrinfo()函数来获取与给定地址和端口相关的地址信息。如果getaddrinfo()返回非零值,表示出现错误,该错误消息会被打印到标准错误输出,并返回一个无效的套接字描述符。
- 接下来,代码会遍历获取到的地址信息,尝试为每个地址创建一个套接字并连接到该地址。如果成功,它会继续尝试下一个地址。如果套接字创建或连接失败,它会关闭套接字并继续处理下一个地址。
- 最后,使用freeaddrinfo()函数释放之前获取的地址信息,并返回创建的套接字描述符。如果连接成功,它将是一个有效的套接字描述符;如果连接失败,它将是一个无效的套接字描述符。
函数说明:
getaddrinfo 函数 (ws2tcpip.h) - Win32 apps | Microsoft Learn
getnameinfo 函数 (ws2tcpip.h) - Win32 apps | Microsoft Learn
getaddrinfo(3) - Linux manual page
getnameinfo(3) - Linux manual page
getaddrinfo()是一个用于网络编程的函数,它用于将主机名和服务名解析为网络地址结构。这个函数是在套接字编程中经常使用的,特别是在处理DNS查找和地址解析时。
函数原型通常如下:
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
参数说明:
- node:主机名或IP地址字符串。如果为NULL,表示使用通配地址。
- service:服务名或端口号字符串。如果为NULL,表示使用默认服务。
- hints:指向一个addrinfo结构体的指针,该结构体包含用于指导地址解析的提示信息。例如,可以指定地址族、套接字类型和协议。
- res:指向一个指向addrinfo结构的指针的指针,该结构体将包含解析出的地址信息。 返回值:
- 如果成功,返回0,并将res指向一个链表,链表中包含解析出的地址信息。
- 如果失败,返回一个非零错误码,并将res设置为NULL。
使用getaddrinfo()函数,你可以将主机名和服务名解析为网络地址结构,这在创建套接字、绑定地址和进行网络通信时非常有用。该函数能够处理各种地址类型和协议,使得在网络编程中更加灵活和方便。
getnameinfo()是一个用于网络编程的函数,它用于将网络地址结构(通常由getaddrinfo()函数返回)转换为主机名和服务名。这个函数是在套接字编程中经常使用的,特别是在处理DNS查找和地址解析时。
函数原型通常如下:
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags);
参数说明:
- sa:指向一个sockaddr结构的指针,该结构包含要解析的网络地址。
- salen:sockaddr结构的大小。
- host:指向一个字符数组的指针,用于存储解析出的主机名。
- hostlen:host数组的大小。
- serv:指向一个字符数组的指针,用于存储解析出的服务名。
- servlen:serv数组的大小。
- flags:一组标志位,用于控制函数的行为。例如,NI_NUMERICHOST表示主机名应以数字形式返回,而NI_NUMERICSERV表示服务名应以数字形式返回。 返回值:
- 如果成功,返回0。
- 如果失败,返回一个非零错误码。
使用getnameinfo()函数,你可以将网络地址转换为可读的主机名和服务名,这在调试、日志记录或用户界面中可能是非常有用的。
getaddrinfo一些资料
它的由来:
getaddrinfo函数的由来可以追溯到IPv4和IPv6共存的时期。在早期,网络编程主要使用gethostbyname系列函数来将主机名转换为IP地址。然而,随着IPv6的普及和网络协议的发展,传统的gethostbyname函数逐渐无法满足需求。由于IPv6地址是128位,传统的点分十进制表示法不再适用,需要使用新的表示法。此外,随着网络协议的多样化和复杂化,应用程序需要更灵活的方式来处理不同的协议和套接字类型。
为了解决这些问题,getaddrinfo函数被引入到网络编程中。它是在1990年代末期设计的,并在POSIX.1-2001标准中被正式定义。该函数最初是为了支持IPv6而设计的,但后来也被扩展到支持IPv4。
getaddrinfo函数的设计目标是提供一个统一的接口,用于将主机名和服务名转换为套接字地址结构,同时支持IPv4和IPv6。它隐藏了底层协议的复杂性,使得应用程序可以更加方便地处理网络地址和端口的转换。
该函数最初是在Unix-like操作系统中实现的,但后来也被移植到了其他操作系统中,如Windows。在Windows系统中,getaddrinfo函数是通过Winsock2 API提供的,并且与IPv6的兼容性更好。
综上所述,getaddrinfo函数的由来是为了解决IPv4和IPv6共存时期的需求,提供一种更加灵活、方便的网络地址转换接口。它是在1990年代末期设计的,并在POSIX标准中被定义。该函数最初是为了支持IPv6而设计的,但后来也被扩展到支持IPv4,并且被广泛应用于各种操作系统中。
该函数的作用主要包括:
1. 名字到地址以及服务到端口的转换。它返回一个sockaddr结构的链表,这些sockaddr地址结构随后可有套接口函数(socket、bind、connect、listen等)直接调用,将协议相关性隐藏在该函数内部。
2. 隐藏协议相关性。应用程序只要处理由getaddrinfo函数填写的套接口地址结构,不需要考虑数据尾端,地址转换等。
getaddrinfo的原理是:根据hints参数指定的参数要求,获取服务器信息,并将获取的结果存储到res中。如果应用程序需要使用主机名代替IP地址,或服务名代替端口号,需要先把对应关系增加到对应的配置文件中,否则getaddrinfo会解析出错。
此外,getaddrinfo函数在POSIX规范中定义,它能够处理协议无关的转换,既可用于IPv4也可用于IPv6。它能够根据给定的主机名和服务名,返回一个包含用于创建套接字对象的五元组(包含地址族、套接字类型、协议等)。
getaddrinfo函数还有一些其他的特点和作用:
1. 地址和端口号转换:除了将主机名转换为IP地址外,getaddrinfo还可以将服务名转换为端口号。这对于一些非标准的服务名(如“http”或“ftp”)尤其有用,这些服务名无法通过传统的getservbyname函数直接转换。
2. 套接字类型和协议处理:getaddrinfo可以根据需要进行协议和套接字类型的转换。这使得应用程序可以更灵活地处理不同的网络协议和套接字类型,而无需自行处理底层细节。
3. 错误处理:getaddrinfo函数在出现错误时会返回一个特定的错误码,而不是直接失败。这使得应用程序能够更好地处理错误情况,并采取适当的措施。
4. 异步操作:getaddrinfo函数支持异步操作,这意味着它可以在后台进行地址解析,而不会阻塞应用程序的主线程。这对于需要快速响应的应用程序非常有用。
5. 可移植性:getaddrinfo函数的设计考虑到了跨平台可移植性。无论是在IPv4还是IPv6环境下,它都能够返回适用于任何协议族的地址。这使得使用getaddrinfo的应用程序更加易于移植和维护。
总的来说,getaddrinfo函数在网络编程中起着重要的作用,它使得应用程序可以更方便、灵活地处理网络地址和端口的转换,同时还隐藏了底层协议的复杂性。
除了上述提到的特点,getaddrinfo函数还有以下一些重要功能:
1. 负载均衡和故障转移:通过getaddrinfo函数,可以获取主机名对应的多个IP地址,从而实现负载均衡和故障转移。当某个IP地址出现故障时,可以自动切换到其他可用的IP地址上。
2. 可重入性:getaddrinfo函数的可重入性取决于其内部调用的gethostbyname和getservbyname函数是否是它们的可重入版本。这意味着该函数可以在多线程环境中安全使用,而不会产生竞态条件。
3. IPv6支持:getaddrinfo函数是协议无关的,既可用于IPv4也可用于IPv6。在IPv6环境中,它能够处理IPv6地址的转换,使得应用程序能够更好地支持IPv6协议。
4. 地址结构链表:getaddrinfo函数返回的是一个addrinfo结构的链表,每个结构体包含了一个地址的信息,包括IP地址、端口号、协议类型等。这个链表可以由套接字函数直接使用,简化了网络编程的复杂性。
5. 兼容性:getaddrinfo函数兼容了传统的gethostbyname和getservbyname函数,这意味着在某些情况下,可以使用这些函数作为替代方案。然而,由于getaddrinfo函数具有更多的功能和更好的性能,因此推荐使用该函数进行网络名称解析。
综上所述,getaddrinfo函数在网络编程中起着非常重要的作用,它提供了一种方便、灵活、可靠的方式来处理网络地址和端口的转换。通过使用该函数,应用程序可以更好地支持各种网络协议和地址类型,同时简化网络编程的复杂性。
函数的原理:
getaddrinfo函数的原理是通过DNS(Domain Name System)进行主机名解析。DNS是一个分布式的命名系统,用于将主机名转换为IP地址。当使用getaddrinfo函数时,它会调用系统的DNS解析库,向DNS服务器发送查询请求,获取主机名对应的IP地址。
getaddrinfo函数的设计目标是提供一个统一的接口,用于将主机名和服务名转换为套接字地址结构,同时支持IPv4和IPv6。它隐藏了底层协议的复杂性,使得应用程序可以更加方便地处理网络地址和端口的转换。
工作原理可以分为以下几个步骤:
1. 参数检查:getaddrinfo函数首先会检查传入的参数是否有效。这些参数包括主机名、服务名、套接字类型和协议类型等。如果参数无效,函数将返回错误码。
2. 模板检查:getaddrinfo函数可以接受一个名为hints的参数,该参数指定了期望的地址类型。函数会根据hints参数中的值来过滤返回的地址结构。如果hints参数为空,函数将返回所有可用的地址结构。
3. DNS查询:getaddrinfo函数调用系统的DNS解析库,向DNS服务器发送查询请求,以获取主机名对应的IP地址。如果主机名是一个域名,函数将尝试将其解析为IP地址。如果主机名是一个IP地址,函数将直接使用该地址。
4. 地址转换:在获取到IP地址后,getaddrinfo函数会根据hints参数中的值进行地址转换。如果hints参数指定了特定的套接字类型或协议类型,函数将尝试将其转换为对应的地址结构。
5. 链表构建:getaddrinfo函数将返回一个addrinfo结构的链表,每个结构体包含了一个地址的信息,包括IP地址、端口号、协议类型等。这个链表可以由套接字函数直接使用,简化了网络编程的复杂性。
6. 错误处理:如果在查询过程中出现错误,getaddrinfo函数将返回一个错误码。应用程序可以通过检查返回值来判断是否出现了错误,并根据需要进行相应的处理。
综上所述,getaddrinfo函数的原理是通过DNS进行主机名解析,并返回一个addrinfo结构的链表。它通过隐藏底层协议的复杂性,使得应用程序可以更加方便地处理网络地址和端口的转换。
getaddrinfo函数虽然具有很多优点,但也存在一些缺点。以下是一些可能的缺点:
1. 性能开销:相对于传统的gethostbyname函数,getaddrinfo函数需要进行DNS查询,这会增加一定的性能开销。对于频繁进行地址转换的应用程序,可能会影响性能。
2. 依赖DNS:getaddrinfo函数依赖于DNS进行主机名解析,如果DNS服务器不可用或者网络连接出现问题,可能会导致函数调用失败。这对于需要可靠的网络连接的应用程序可能会造成问题。
3. 参数复杂:getaddrinfo函数的参数相对较多,使用起来可能比传统的gethostbyname函数更复杂。对于不熟悉该函数的应用程序开发者,可能需要花费更多的时间和精力来理解和使用它。
4. IPv4和IPv6的兼容性:虽然getaddrinfo函数可以同时支持IPv4和IPv6,但在处理不同协议的地址时需要进行相应的转换。这可能增加了代码的复杂性和开发难度。
5. 错误处理:虽然getaddrinfo函数在出现错误时会返回一个特定的错误码,但对于某些错误情况可能没有提供足够的上下文信息。这可能使得错误处理变得困难,特别是当错误发生在异步操作中时。
综上所述,虽然getaddrinfo函数具有很多优点,但也存在一些缺点。在使用该函数时,需要权衡其优点和缺点,并根据应用程序的需求进行选择。在一些特定的情况下,可能需要使用其他的网络编程接口或方法来满足需求。
应用场景:
getaddrinfo函数广泛应用于各种需要进行网络连接的场景中,尤其是在处理主机名和服务名到套接字地址的转换时。以下是几个常见的应用场景:
1. 简单的HTTP客户端:可以使用getaddrinfo函数来实现一个简单的HTTP客户端,用于向Web服务器发送HTTP请求。通过将主机名和服务名转换为套接字地址结构,可以方便地建立与远程服务器的连接。
2. DNS查询:在DNS查询过程中,getaddrinfo函数可以用于将域名解析为IP地址。当应用程序需要将主机名转换为IP地址时,可以使用该函数来获取对应的IP地址列表。
3. 网络连接建立:在网络应用程序中,当需要建立与服务器的连接时,可以使用getaddrinfo函数来获取服务器端的IP地址和端口号。然后,使用这些信息来创建套接字并建立连接。
4. 负载均衡和故障转移:通过getaddrinfo函数,可以获取主机名对应的多个IP地址,从而实现负载均衡和故障转移。当某个IP地址出现故障时,可以自动切换到其他可用的IP地址上。
5. 多协议支持:getaddrinfo函数能够处理协议无关的转换,既可用于IPv4也可用于IPv6。在多协议环境下,应用程序可以使用该函数来处理不同协议的网络地址转换。
综上所述,getaddrinfo函数在各种需要进行网络连接的场景中都有广泛的应用,无论是简单的HTTP客户端还是复杂的网络应用程序,都可以通过该函数来方便地处理网络地址和端口的转换。
相关推荐
- 详解 HTTPS、TLS、SSL、HTTP区别和关系
-
一、什么是HTTPS、TLS、SSLHTTPS,也称作HTTPoverTLS。TLS的前身是SSL,TLS1.0通常被标示为SSL3.1,TLS1.1为SSL3.2,TLS1.2为SSL...
- 锐安信SSL证书自动化运维系统:灵活管理SSL/TLS证书全生命周期
-
点击上方关注“锐成云分销”,云建站解决方案专家!域名、SSL证书、DNS、主机一站选齐在SSL/TLS证书的生命周期管理中,证书的各种操作方式是基础且核心的部分之一,更是保障用户数据传输加密的关键。这...
- 宝塔免费的 SSL/TLS 证书如何续签
-
申请之前,请确保域名已解析,如未解析会导致审核失败(包括根域名)宝塔SSL申请的是免费版TrustAsiaDVSSLCA-G5证书,仅支持单个域名申请有效期1年,不支持续签,到期后需要重新申...
- HTTPS、HTTP、TLS/SSL工作及握手原理、PKI/CA密钥体系
-
一、HTTPS与HTTP介绍二、TLS/SSL工作原理三、TSL/SSL握手过程四、HTTPS性能优化五、PKI体系一、HTTPS与HTTP介绍1.Https(SecureHypetextTran...
- 什么是SSL证书卸载 SSL证书卸载有什么作用
-
SSL证书是数字证书的一种,安装部署的话可以对网站起到身份验证和数据加密的作用。网站部署SSL证书,相对就必然会有SSL证书卸载,那么SSL证书卸载是什么呢?SSL证书卸载有什么作用?随着SSL通信量...
- 让SSL/TLS协议流行起来:深度解读SSL/TLS实现1
-
一前言SSL/TLS协议是网络安全通信的重要基石,本系列将简单介绍SSL/TLS协议,主要关注SSL/TLS协议的安全性,特别是SSL规范的正确实现。本系列的文章大体分为3个部分:SSL/TLS协...
- 苹果、谷歌、微软等一致同意!SSL/TLS证书最长有效期锐减至47天
-
快科技4月14日消息,苹果此前向CA/B论坛(负责管理SSL/TLS证书的行业组织)提议,将所有证书有效期缩短至45天。日前CA/B论坛服务器证书工作组投票通过SC-081v3提案,最终决定将SSL/...
- Android怎么设置端口转发,将访问本设备的端口转到另外一台设备
-
一、Android系统怎么设置端口转发,将访问本设备的端口转到另外一台设备?要设置端口转发,您需要先在Android设备上安装一个支持端口转发的应用程序。其中一个常用的应用是"Termux...
- 大神级产品:手机装 Linux 运行 Docker 如此简单
-
本内容来源于@什么值得买APP,观点仅代表作者本人|作者:灵昱Termux作为一个强大的Android终端模拟器,能够运行多种Linux环境。然而,直接在Termux上运行Docker并不可行,需要...
- 关于H3C交换机的SSH功能配置方法(华三交换机ssh配置)
-
对于交换机的初步学习,作为初学者的我,还望诸位不吝赐教。若存在不足之处,烦请大家多提宝贵意见。同样身为初学者的我们,亦可携手共进,相互分享技术经验。一、本地用户配置(核心步骤)1.创建用户并设置密码...
- Linux常用操作ssh(linux中的ssh命令)
-
ssh#p是小写ssh-p22user@hostsftp#连接sftp-P22root@host#将文件上传到服务器上:put[本地文件的地址][服务器上文件存储的位置]#将...
- 小白心得,如何使用SSH连接飞牛系统(fnos)?
-
一、背景作为一个刚接触飞牛系统的小白,在研究飞牛os的时候,发现很多功能都需要连接ssh,但是如何使用SSH连接飞牛系统成为入门飞牛os的一道坎。下面以自己的学习经历详细记录下过程吧。二、系统设置1、...
- 如何在 Windows 11 或 10 上使用 Winget 安装 OpenSSH
-
SSH(SecureShell)是大多数开发人员和系统管理员用来通过Linux远程连接托管服务器或任何云服务的工具,因为SSH在Linux中是内置的。然而,对于Windows呢?是的...
- linux文件之ssh配置文件的含义与作用
-
ssh远程登录命令是操作系统(包括linux和window系统)下常用的操作命令,可以帮助用户,远程登录服务器系统,查看,操作系统相关信息。linux系统对于ssh命令有专门保存其相关配置的目录和文件...
- 害怕Linux SSH不安全?这几个小妙招安排上!
-
ssh是访问远程服务器最常用的方法之一,同时,其也是Linux服务器受到攻击的最常见的原因之一。不过别误会...我们并不是说ssh有什么安全漏洞,相反,它在设计上是一个非常安全的协议。但是安...
你 发表评论:
欢迎- 一周热门
-
-
如何在安装前及安装后修改黑群晖的Mac地址和Sn系列号
-
爱折腾的特斯拉车主必看!手把手教你TESLAMATE的备份和恢复
-
[常用工具] OpenCV_contrib库在windows下编译使用指南
-
Ubuntu系统Daphne + Nginx + supervisor部署Django项目
-
WindowsServer2022|配置NTP服务器的命令
-
WIN11 安装配置 linux 子系统 Ubuntu 图形界面 桌面系统
-
解决Linux终端中“-bash: nano: command not found”问题
-
极空间如何无损移机,新Z4 Pro又有哪些升级?极空间Z4 Pro深度体验
-
NBA 2K25虚拟内存不足/爆内存/内存占用100% 一文速解
-
Linux 中的文件描述符是什么?(linux 打开文件表 文件描述符)
-
- 最近发表
-
- 详解 HTTPS、TLS、SSL、HTTP区别和关系
- 锐安信SSL证书自动化运维系统:灵活管理SSL/TLS证书全生命周期
- 宝塔免费的 SSL/TLS 证书如何续签
- HTTPS、HTTP、TLS/SSL工作及握手原理、PKI/CA密钥体系
- 什么是SSL证书卸载 SSL证书卸载有什么作用
- 让SSL/TLS协议流行起来:深度解读SSL/TLS实现1
- 苹果、谷歌、微软等一致同意!SSL/TLS证书最长有效期锐减至47天
- Android怎么设置端口转发,将访问本设备的端口转到另外一台设备
- 大神级产品:手机装 Linux 运行 Docker 如此简单
- 关于H3C交换机的SSH功能配置方法(华三交换机ssh配置)
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)