解决 Win10 热点无法上网及与 Hyper-V 虚拟网卡冲突问题

最近给 Win10 电脑加装了一个无线网卡,想要开热点使用,但是发现手机连上之后显示无法联网,在这里记录解决办法。

首先查看一下当前电脑上网使用的网卡是哪一张,我当前使用的是 Hyper-V 虚拟的一个桥接网卡 vEthernet (NetBridge) 开启 wifi 热点后新增的网卡是 本地连接* 12

现在进入上网网卡的属性,进入共享标签,发现 Internet 连接共享是关闭状态,现在将它打开,并将家庭网络连接指定为 wifi 热点的网卡,确认即可。

再次尝试连接即可。

补充:开启连接共享时报错 “无法启用 internet 连接共享,为 lan 连接配置的 ip 地址需要使用自动 ip 寻址” ,将不需要的 Vmware 虚拟网卡卸载后解决,猜测可能是占用了某些共享需要用到的网段导致。

参考文献

NMAP 基础扫描

以下几个示例带领你快速了解nmap的基本扫描方法,更多详情请查阅nmap手册。

1、Nmap 简单扫描

$ nmap <target ip address>
$ nmap 192.168.41.41

直接指定需要扫描的主机IP开始扫描,返回详细描述。

2、Nmap 扫描并输出详细信息

$ nmap <target ip address> -vv
$ nmap 192.168.41.41 -vv

3、Nmap 指定端口范围扫描

$ nmap -p(range) <target IP>
# (rangge)为要扫描的端口(范围),端口大小不能超过65535

# nmap 192.168.41.41 -p1-50
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 16:37 CST
Nmap scan report for bogon (192.168.41.41)
Host is up (0.0038s latency).
Not shown: 46 closed ports
PORT   STATE    SERVICE
5/tcp  filtered rje
21/tcp filtered ftp
23/tcp open     telnet
27/tcp filtered nsw-fe
MAC Address: 00:11:22:33:44:41 (Cimsys)

Nmap done: 1 IP address (1 host up) scanned in 7.99 seconds

4、Nmap 指定端口扫描

$ nmap -p(port1,port2,port3,...) <target ip> 

$ nmap -p23 192.168.41.41
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 16:44 CST
Nmap scan report for bogon (192.168.41.41)
Host is up (0.0083s latency).

PORT   STATE SERVICE
23/tcp open  telnet
MAC Address: 00:11:22:33:44:41 (Cimsys)

Nmap done: 1 IP address (1 host up) scanned in 0.04 seconds

5、Nmap Ping 扫描

$ nmap -sP <target ip> 
$ nmap -sP 192.168.41.41
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 16:45 CST
Nmap scan report for bogon (192.168.41.41)
Host is up (0.0064s latency).
MAC Address: 00:11:22:33:44:41 (Cimsys)
Nmap done: 1 IP address (1 host up) scanned in 0.02 seconds

6、Nmap路由跟踪

$ nmap --traceroute <target ip> 
$  nmap --traceroute 119.29.29.29
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 16:50 CST
Nmap scan report for pdns.dnspod.cn (119.29.29.29)
Host is up (0.019s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE
53/tcp open  domain
80/tcp open  http

TRACEROUTE (using port 80/tcp)
HOP RTT      ADDRESS
1   1.99 ms  bogon (192.168.6.1)
2   2.71 ms  bogon (192.168.169.9)
3   2.71 ms  bogon (192.168.169.1)
4   19.82 ms hn.kd.ny.adsl (123.14.80.1)
5   4.74 ms  hn.kd.ny.adsl (125.40.240.77)
6   6.17 ms  pc93.zz.ha.cn (61.168.37.93)
7   ... 8
9   44.19 ms no-data (125.39.198.178)
10  ... 19
20  19.46 ms pdns.dnspod.cn (119.29.29.29)

Nmap done: 1 IP address (1 host up) scanned in 10.55 seconds

7 Nmap 扫描某网段IP

$ nmap -sP <network address > </CIDR >
$ nmap -sP 192.168.8.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 16:53 CST
Nmap scan report for bogon (192.168.8.129)
Host is up (0.00084s latency).
Nmap done: 256 IP addresses (1 host up) scanned in 19.87 seconds

8、Nmap 探测操作系统类别

$ nmap -O <target ip> 
$  nmap -O 119.29.29.29
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 16:59 CST
Nmap scan report for pdns.dnspod.cn (119.29.29.29)
Host is up (0.021s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE
53/tcp open  domain
80/tcp open  http
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: specialized|media device|WAP
Running (JUST GUESSING): Linux 2.6.X|3.X (88%), Hikvision embedded (88%)
OS CPE: cpe:/o:linux:linux_kernel:2.6.10 cpe:/h:hikvision:ds-7600 cpe:/o:linux:linux_kernel:3.0 cpe:/o:linux:linux_kernel:3.10
Aggressive OS guesses: HIKVISION DS-7600 Linux Embedded NVR (Linux 2.6.10) (88%), Linux 3.0 (88%), DD-WRT v24-sp2 (Linux 3.10) (87%)
No exact OS matches for host (test conditions non-ideal).

OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.49 seconds

9、Nmap 万能扫描

此选项设置包含了1-10000的端口ping扫描,操作系统扫描,脚本扫描,路由跟踪,服务探测。 命令语法:

$ nmap -A <target ip>
$ nmap -A 119.29.29.29
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 17:08 CST
Nmap scan report for pdns.dnspod.cn (119.29.29.29)
Host is up (0.020s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE VERSION
53/tcp open  domain  ISC BIND 9.11.3
| dns-nsid:
|_  bind.version: 9.11.3
80/tcp open  http    Http Server
| fingerprint-strings:
|   FourOhFourRequest, GetRequest:
|     HTTP/1.0 404 Not Found
|     Connection: close
|     Server: Http Server
|     Content-Type: text/html
|     Content-Length: 174
|     
<html>
|     
<head><title>Server error message</title></head>
|     
<body>
|     
<h1>Error 404: Not Found</h1>
|     request could not be completed because:
|     Document not found!
|     </body>
|_    </html>
|_http-server-header: Http Server
|_http-title: Server error message
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port80-TCP:V=7.80%I=7%D=1/26%Time=600FDC05%P=x86_64-redhat-linux-gnu%r(
SF:GetRequest,11E,"HTTP/1\.0\x20404\x20Not\x20Found\r\nConnection:\x20clos
SF:e\r\nServer:\x20Http\x20Server\r\nContent-Type:\x20text/html\r\nContent
SF:-Length:\x20174\r\n\r\n
<html>\n<head><title>Server\x20error\x20message<
SF:/title></head>\n<body>\n<h1>Error\x20404:\x20Not\x20Found</h1>\nThe\x20
SF:request\x20could\x20not\x20be\x20completed\x20because:\n\x20Document\x2
SF:0not\x20found!\n</body>\n</html>\n")%r(FourOhFourRequest,11E,"HTTP/1\.0
SF:\x20404\x20Not\x20Found\r\nConnection:\x20close\r\nServer:\x20Http\x20S
SF:erver\r\nContent-Type:\x20text/html\r\nContent-Length:\x20174\r\n\r\n<h
SF:tml>\n
<head><title>Server\x20error\x20message</title></head>\n<body>\n<
SF:h1>Error\x20404:\x20Not\x20Found</h1>\nThe\x20request\x20could\x20not\x
SF:20be\x20completed\x20because:\n\x20Document\x20not\x20found!\n</body>\n
SF:</html>\n");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: media device|specialized|WAP|security-misc
Running (JUST GUESSING): Linux 3.X|2.6.X (88%), Hikvision embedded (87%), Imperva SecureSphere (86%)
OS CPE: cpe:/o:linux:linux_kernel:3.0 cpe:/o:linux:linux_kernel:2.6.10 cpe:/h:hikvision:ds-7600 cpe:/o:linux:linux_kernel:3.10 cpe:/o:imperva:securesphere
Aggressive OS guesses: Linux 3.0 (88%), HIKVISION DS-7600 Linux Embedded NVR (Linux 2.6.10) (87%), DD-WRT v24-sp2 (Linux 3.10) (87%), Linux 2.6.32 (86%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 20 hops

TRACEROUTE (using port 53/tcp)
HOP RTT      ADDRESS
1   1.83 ms  bogon (192.168.6.1)
2   2.69 ms  bogon (192.168.169.9)
3   2.12 ms  bogon (192.168.169.1)
4   4.01 ms  hn.kd.ny.adsl (123.14.80.1)
5   3.74 ms  hn.kd.ny.adsl (125.40.240.77)
6   5.07 ms  pc73.zz.ha.cn (61.168.37.73)
7   ...
8   17.91 ms dns2.online.tj.cn (117.8.222.2)
9   30.42 ms no-data (125.39.198.178)
10  ... 19
20  20.12 ms pdns.dnspod.cn (119.29.29.29)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 164.97 seconds

10、Nmap 命令混合式扫描

$ nmap -vv -p1-1000 -O <target ip>
$ nmap -vv -p1-50 -O 192.168.41.41
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-26 17:12 CST
Initiating ARP Ping Scan at 17:12
Scanning 192.168.41.41 [1 port]
Completed ARP Ping Scan at 17:12, 0.01s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 17:12
Completed Parallel DNS resolution of 1 host. at 17:12, 0.00s elapsed
Initiating SYN Stealth Scan at 17:12
Scanning bogon (192.168.41.41) [50 ports]
Discovered open port 23/tcp on 192.168.41.41
Increasing send delay for 192.168.41.41 from 0 to 5 due to 13 out of 43 dropped probes since last increase.
Completed SYN Stealth Scan at 17:12, 4.52s elapsed (50 total ports)
Initiating OS detection (try #1) against bogon (192.168.41.41)
Retrying OS detection (try #2) against bogon (192.168.41.41)
Retrying OS detection (try #3) against bogon (192.168.41.41)
Retrying OS detection (try #4) against bogon (192.168.41.41)
Retrying OS detection (try #5) against bogon (192.168.41.41)
Nmap scan report for bogon (192.168.41.41)
Host is up, received arp-response (0.0030s latency).
Scanned at 2021-01-26 17:12:37 CST for 16s

PORT   STATE    SERVICE     REASON
1/tcp  closed   tcpmux      reset ttl 64
2/tcp  filtered compressnet no-response
3/tcp  closed   compressnet reset ttl 64
4/tcp  closed   unknown     reset ttl 64
5/tcp  closed   rje         reset ttl 64
6/tcp  closed   unknown     reset ttl 64
7/tcp  closed   echo        reset ttl 64
8/tcp  closed   unknown     reset ttl 64
9/tcp  closed   discard     reset ttl 64
10/tcp closed   unknown     reset ttl 64
11/tcp closed   systat      reset ttl 64
12/tcp closed   unknown     reset ttl 64
13/tcp closed   daytime     reset ttl 64
14/tcp closed   unknown     reset ttl 64
15/tcp closed   netstat     reset ttl 64
16/tcp closed   unknown     reset ttl 64
17/tcp closed   qotd        reset ttl 64
18/tcp closed   msp         reset ttl 64
19/tcp closed   chargen     reset ttl 64
20/tcp closed   ftp-data    reset ttl 64
21/tcp closed   ftp         reset ttl 64
22/tcp closed   ssh         reset ttl 64
23/tcp open     telnet      syn-ack ttl 64
24/tcp closed   priv-mail   reset ttl 64
25/tcp closed   smtp        reset ttl 64
26/tcp closed   rsftp       reset ttl 64
27/tcp closed   nsw-fe      reset ttl 64
28/tcp closed   unknown     reset ttl 64
29/tcp closed   msg-icp     reset ttl 64
30/tcp closed   unknown     reset ttl 64
31/tcp closed   msg-auth    reset ttl 64
32/tcp closed   unknown     reset ttl 64
33/tcp closed   dsp         reset ttl 64
34/tcp closed   unknown     reset ttl 64
35/tcp closed   priv-print  reset ttl 64
36/tcp closed   unknown     reset ttl 64
37/tcp closed   time        reset ttl 64
38/tcp closed   rap         reset ttl 64
39/tcp closed   rlp         reset ttl 64
40/tcp closed   unknown     reset ttl 64
41/tcp closed   graphics    reset ttl 64
42/tcp closed   nameserver  reset ttl 64
43/tcp closed   whois       reset ttl 64
44/tcp closed   mpm-flags   reset ttl 64
45/tcp closed   mpm         reset ttl 64
46/tcp closed   mpm-snd     reset ttl 64
47/tcp closed   ni-ftp      reset ttl 64
48/tcp filtered auditd      no-response
49/tcp closed   tacacs      reset ttl 64
50/tcp closed   re-mail-ck  reset ttl 64
MAC Address: 00:11:22:33:44:41 (Cimsys)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=1/26%OT=23%CT=1%CU=37223%PV=Y%DS=1%DC=D%G=Y%M=001122%T
OS:M=600FDD15%P=x86_64-redhat-linux-gnu)SEQ(SP=105%GCD=1%ISR=10C%TI=Z%CI=RD
OS:%TS=A)SEQ(SP=104%GCD=1%ISR=10C%TI=Z%CI=RI%II=I%TS=A)OPS(O1=M5A0ST11NW7%O
OS:2=M5A0ST11NW7%O3=M5A0NNT11NW7%O4=M5A0ST11NW7%O5=M5A0ST11NW7%O6=M5A0ST11)
OS:WIN(W1=6F90%W2=6F90%W3=6F90%W4=6F90%W5=6F90%W6=6F90)ECN(R=Y%DF=Y%T=40%W=
OS:7080%O=M5A0NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=Y%
OS:DF=Y%T=2B%W=80%S=A%A=Z%F=R%O=WANM109T10S%RD=0%Q=)T3(R=N)T4(R=Y%DF=Y%T=38
OS:%W=400%S=A%A=Z%F=R%O=WANM109T10S%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=A%A=S+%F
OS:=AR%O=%RD=0%Q=)T5(R=N)T6(R=Y%DF=Y%T=34%W=8000%S=A%A=Z%F=R%O=WANM109T10S%
OS:RD=0%Q=)T7(R=Y%DF=N%T=26%W=FFFF%S=A%A=Z%F=R%O=WFNM109T10S%RD=0%Q=)U1(R=Y
OS:%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T
OS:=40%CD=S)

Uptime guess: 34.815 days (since Tue Dec 22 21:38:45 2020)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros

Read data files from: /usr/bin/../share/nmap
OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.95 seconds
           Raw packets sent: 187 (12.130KB) | Rcvd: 159 (10.202KB)

参考文献

Linux 多进程通信开发之 UNIX domain Socket 通信机制从 TCP 切换为 UDP

Unix domain socket 或者 IPC socket是一种终端,可以使同一台操作系统上的两个或多个进程进行数据通信。提供 UDP 和 TCP 两种通信机制。

因为一些原因,项目现有软件架构采用的都是 IPC sockte 中的 TCP 通信机制,虽然保证了通信的可靠性,但近期需要对该程序进行热迁移(基于 criu ),有连接的 IPC 套接字状态很难被保存和恢复,而 无连接的 UDP 只需要保证服务端先冻结、先恢复即可实现程序整体状态迁移,因此写下本文,记录迁移过程,最后提供示例程序,可以自行通过 BCompare 等文本对比工具对比差异。

模式差异

至于两种通信机制的差异,除了在创建套接字时声明的差异,具体的通信流程也有差异,在这里找到 CSDN @frank909 的两张图片,感觉很有代表性,在这里引用一下。

首先是 TCP的:

https://imagehost-cdn.frytea.com/images/2021/01/13/202101131815253d04d69f377dae01.png

https://imagehost-cdn.frytea.com/images/2021/01/13/202101131815253d04d69f377dae01.png

接下来是 UDP 的:

https://imagehost-cdn.frytea.com/images/2021/01/13/2021011318145069f28463e2e1709c.png

二者的差异,主要是这几点:

  • 服务端:

(1)TCP连接在 bind() 之后需要 listen() ,而UDP不需要。

(2)TCP连接在 bind()listen() 后还需要 accept(),用来得到客户端连接描述符,而UDP不需要。

(3)收发数据,TCP使用 recv() , send() , 而 UDP 使用 recvfrom(), sendto()

(4)释放连接,TCP在客户端释放连接后需先释放 accept() 得到的客户端连接描述符,再 close(socket) ,而UDP直接 close(socket)

  • 客户端:

(1)TCP连接在bind()后需要 connect(),而UDP不需要。

(2)收发数据,TCP使用 recv() , send() , 而 UDP 使用 recvfrom(), sendto()

具体的差异可以查看下方的示例程序。

参考程序

TCP-Server

/*************************************************************************
  > File Name: ipc_tcp_server.cpp
  > Author: TianLun Song
  > Mail: songtianlun@frytea.com
  > Blog: https://blog.frytea.com
  > Created Time: Wed 13 Jan 2021 09:53:06 AM CST
 ************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <memory.h>
#include <unistd.h>
#include <stdio.h>
#include 
<iostream>

using namespace std;
const char* server_file = "/tmp/ipc_tcp_server.sock";

int main(int argc,char** argv)
{
    int socket_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if (socket_fd < 0)
    {
        perror("socket");
        return -1;
    }
    struct sockaddr_un addr;
    memset(&addr,0,sizeof(addr));
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path,server_file);
    if (access(addr.sun_path,0) != -1)
    {
        remove(addr.sun_path);
    }
    if (bind(socket_fd,(sockaddr*)&addr,sizeof(addr)) < 0)
    {
        perror("bind");
        return -1;
    }
    /* --------DIFF, ipc tcp only------------ */
    if (listen(socket_fd,12) < 0)
    {
        perror("listen");
        return -1;
    }
    /* ---------------end------------ */
    struct sockaddr_un clientaddr;
    socklen_t addrlen = sizeof(clientaddr);
    char msg_buf[1024];
    /* --------DIFF, ipc tcp only------------ */
    int newcon = -1;
    newcon = accept(socket_fd,(sockaddr*)&clientaddr,&addrlen);
    if (newcon < 0)
    {
        perror("accept");
        return -1;
    }
    /* ---------------end------------ */
    while (1)
    {
        memset(msg_buf,'\0',1024);
        int rsize = recv(newcon,msg_buf,sizeof(msg_buf),0);
        if (rsize < 0)
        {
            perror("server recv error!");
            break;
        }
        cout << "I'm Unix socket(TCP) server, recv a msg:" << msg_buf << " from: " << clientaddr.sun_path << endl;
        strcpy(msg_buf, "OK,I got it!");
        int ssize = send(newcon, msg_buf, sizeof msg_buf, 0);
        if (ssize < 0)
        {
            perror("server send error!");
            break;
        }
        sleep(1);
    }
    /* --------DIFF, ipc tcp only------------ */
    if (close(newcon) < 0)
    {
        perror("close accept");
        return -1;
    }
    /* ---------------end------------ */
    if (close(socket_fd) < 0)
    {
        perror("close socket");
        return -1;
    }
    return 0;
}

TCP-Client

/*************************************************************************
  > File Name: ipc_tcp_client.cpp
  > Author: TianLun Song
  > Mail: songtianlun@frytea.com
  > Blog: https://blog.frytea.com
  > Created Time: Wed 13 Jan 2021 10:14:09 AM CST
 ************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <memory.h>
#include <unistd.h>
#include <stdio.h>
#include 
<iostream>

using namespace std;

const char* server_file = "/tmp/ipc_tcp_server.sock";
const char* client_file = "/tmp/ipc_tcp_client.sock";

int main(int argc,char** argv)
{
    int socket_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if (socket_fd < 0)
    {
        perror("client socket");
        return -1;
    }
    struct sockaddr_un client_addr;
    memset(&client_addr,0,sizeof(client_addr));
    client_addr.sun_family = AF_UNIX;
    strcpy(client_addr.sun_path,client_file);

    if (access(client_addr.sun_path,0) != -1)
    {
        remove(client_addr.sun_path);
    }

    if(bind(socket_fd,(sockaddr*)&client_addr,sizeof(client_addr)) < 0)
    {
        perror("client bind");
        return -1;
    }
    struct sockaddr_un serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    socklen_t addrlen = sizeof(serveraddr);
    serveraddr.sun_family = AF_UNIX;
    strcpy(serveraddr.sun_path,server_file);
    char msg_buf[1024];
    /* --------DIFF, ipc tcp only------------ */
    int newcon = -1;
    newcon = connect(socket_fd,(sockaddr*)&serveraddr,addrlen);
    if (newcon < 0){
        perror("client connect");
    }
    /* ---------------end------------ */
    while(1)
    {
        strcpy(msg_buf, "How are you !!!");
        int ssize = send(socket_fd, msg_buf, sizeof msg_buf, 0);
        if (ssize < 0)
        {
            perror("client send");
            continue;
        }
        int rsize = recv(socket_fd, msg_buf, sizeof(msg_buf), 0);
        if (rsize < 0)
        {
            perror("client recv");
            continue;
        }
        cout << "I'm Unix socket(TCP) client,receive a msg :" << msg_buf << endl;
        sleep(1);
    }
    if (close(socket_fd) < 0)
    {
        perror("close");
        return -1;
    }
    return 0;
}

UDP-Server

/*************************************************************************
  > File Name: ipc_udp_server.cpp
  > Author: TianLun Song
  > Mail: songtianlun@frytea.com
  > Blog: https://blog.frytea.com
  > Created Time: Wed 13 Jan 2021 09:53:06 AM CST
 ************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <memory.h>
#include <unistd.h>
#include <stdio.h>
#include 
<iostream>

using namespace std;
const char* server_file = "/tmp/ipc_udp_server.sock";

int main(int argc,char** argv)
{
    int socket_fd = socket(AF_UNIX,SOCK_DGRAM,0);
    if (socket_fd < 0)
    {
        perror("socket");
        return -1;
    }
    struct sockaddr_un addr;
    memset(&addr,0,sizeof(addr));
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path,server_file);
    if (access(addr.sun_path,0) != -1)
    {
        remove(addr.sun_path);
    }
    if (bind(socket_fd,(sockaddr*)&addr,sizeof(addr)) < 0)
    {
        perror("bind");
        return -1;
    }
    struct sockaddr_un clientaddr;
    socklen_t addrlen = sizeof(clientaddr);
    char msg_buf[1024];
    while (1)
    {
        memset(msg_buf,'\0',1024);
        int rsize = recvfrom(socket_fd,msg_buf,sizeof(msg_buf),0,(sockaddr*)&clientaddr,&addrlen);
        if (rsize < 0)
        {
            perror("server recv error!");
            break;
        }
        cout << "I'm Unix socket(UDP) server, recv a msg: " << msg_buf  << " from: " << clientaddr.sun_path << endl;
        strcpy(msg_buf, "OK,I got it!");
        int ssize = sendto(socket_fd, msg_buf, sizeof msg_buf,0,(sockaddr*)&clientaddr,addrlen);
        if (ssize < 0)
        {
            perror("server send error!");
            break;
        }
        sleep(1);
    }
    if (close(socket_fd) < 0)
    {
        perror("close socket");
        return -1;
    }
    return 0;
}

UDP-Client

/*************************************************************************
  > File Name: ipc_udp_client.cpp
  > Author: TianLun Song
  > Mail: songtianlun@frytea.com
  > Blog: https://blog.frytea.com
  > Created Time: Wed 13 Jan 2021 10:14:09 AM CST
 ************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <memory.h>
#include <unistd.h>
#include <stdio.h>
#include 
<iostream>

using namespace std;

const char* server_file = "/tmp/ipc_udp_server.sock";
const char* client_file = "/tmp/ipc_udp_client.sock";

int main(int argc,char** argv)
{
    int socket_fd = socket(AF_UNIX,SOCK_DGRAM,0);
    if (socket_fd < 0)
    {
        perror("client socket");
        return -1;
    }
    struct sockaddr_un client_addr;
    memset(&client_addr,0,sizeof(client_addr));
    client_addr.sun_family = AF_UNIX;
    strcpy(client_addr.sun_path,client_file);

    if (access(client_addr.sun_path,0) != -1)
    {
        remove(client_addr.sun_path);
    }

    if(bind(socket_fd,(sockaddr*)&client_addr,sizeof(client_addr)) < 0)
    {
        perror("client bind");
        return -1;
    }
    struct sockaddr_un serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    socklen_t addrlen = sizeof(serveraddr);
    serveraddr.sun_family = AF_UNIX;
    strcpy(serveraddr.sun_path,server_file);
    char msg_buf[1024];
    while(1)
    {
        strcpy(msg_buf, "How are you !!!");
        int ssize = sendto(socket_fd, msg_buf, sizeof msg_buf, 0, (sockaddr*)&serveraddr,addrlen);
        if (ssize < 0)
        {
            perror("client sendto");
            continue;
        }
        int rsize = recvfrom(socket_fd, msg_buf, sizeof(msg_buf), 0,(sockaddr*)&serveraddr, &addrlen);
        if (rsize < 0)
        {
            perror("client recv");
            continue;
        }
        cout << "I'm Unix socket(TCP) client,receive a msg :" << msg_buf << endl;
        sleep(1);
    }
    if (close(socket_fd) < 0)
    {
        perror("close");
        return -1;
    }
    return 0;
}

源文件

ipc_test.zip

参考文献

无需代理直接加速各种 GitHub 资源拉取 | 国内镜像赋能 | 助力开发

常见的github加速方法如修改 hosts 文件、魔法上网、设置 proxy 等方法在此不在赘述,本文主要介绍在不进行多余网络配置的情况下,直接使用提供了github国内镜像服务的网站进行github各种资源拉取加速,在这里向各位提供github国内镜像服务的大佬们致敬。

加速地址一览

加速 clone

# 方法一:手动替换地址
#原地址
$ git clone https://github.com/kubernetes/kubernetes.git
#改为
$ git clone https://github.com.cnpmjs.org/kubernetes/kubernetes.git
#或者
$ git clone https://hub.fastgit.org/kubernetes/kubernetes.git
#或者
$ git clone https://gitclone.com/github.com/kubernetes/kubernetes.git

# 方法二:配置git自动替换
$ git config --global url."https://hub.fastgit.org".insteadOf https://github.com
# 测试
$ git clone https://github.com/kubernetes/kubernetes.git
# 查看git配置信息
$ git config --global --list
# 取消设置
$ git config --global --unset url.https://github.com/.insteadof

加速 release

# 原地址
wget https://github.com/goharbor/harbor/releases/download/v2.0.2/harbor-offline-installer-v2.0.2.tgz
# 加速下载方法一
wget https://download.fastgit.org/goharbor/harbor/releases/download/v2.0.2/harbor-offline-installer-v2.0.2.tgz
# 加速下载方法二
wget https://hub.fastgit.org/goharbor/harbor/releases/download/v2.0.2/harbor-offline-installer-v2.0.2.tgz

加速 raw

# 原地址
$ wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/README.md
# 加速下载方法一
$ wget https://raw.staticdn.net/kubernetes/kubernetes/master/README.md
# 加速下载方法二
$ wget https://raw.fastgit.org/kubernetes/kubernetes/master/README.md

参考文献

小狗钱钱 | 伪装成童话的入门理财书籍

如果你只是带着试试看的心态,那么你最后只会以失败而告终,你会一事无成。尝试纯粹是一种借口,你还没有做,就已经给自己想好退路了。不能试验。你只有两个选择:做,或者不做。

全书开篇就给人确立了必做的决心,读到这里还会继续读下去,在心里或多或少都已经做好了“一定要掌控财富”的决心了吧。个人认为这也是本书厉害之处,几乎没有强迫、说教的口吻,但给人一种“必做”且想想自己“能做”的感觉,这也许就是故事的魅力所在吧。

财富第一要素 —— 自信

是不是谈到钱,心里就会感觉很无力,似乎那并不是自己所能控制的。老板、家人给多少,我就有多少,但这财富的积累、增长都是我不能够左右的?实际上并不是这样,许多时候之所以能够做成一件事,是因为我相信自己能够做到。在外面工作、学习,需要的人也常常是这种相信自己能够做成的人。 —— 这个世界需要自信又能干的人

是否能挣到钱,最关键的因素并不在于你是不是有一个好点子,你有多聪明也不是主要原因,决定因素是你的自信程度。

财富第二要素 —— 扬长避短

有了自信,我们就跨出了第一步,接下来如何去做呢?做什么事情可以让我赚取更多的财富呢?那就需要找到自己真正擅长的事情,专注于自己的长处,使其发挥最大的力量。

一个人把精力集中在自己所能做的,知道的和拥有的东西上的那一天起,他的成功就已经拉开了序幕。这也使得一个孩子完全有能力比成人挣到更多的钱。

这时可能有人要问了,如何将精力集中在自己擅长的事情上呢?这里就有得说了,文中提到了一种方法 —— 成功日记。简单来说就是将一天当中自己认为做的很成功的事情记下来,就像日记一样每天记录,久而久之就成了自己的成功日记。

成功日记不仅仅是记录下自己这些成功的事情,它更大的价值在于日后我们翻看这些日记时,会从中得到很多力量、自信还有方向。人们会从成功的事情上感受到成就感,久而久之就会将注意力不由自主的放在自己所擅长的事情上,这样时间长了就可以自然而然做到“扬长避短”啦。

财富第三要素 —— 正确投资

有人开玩笑总结过一句话:不理财是等死,瞎理财是找死。是不是很生动?那么如何才是正确的投资理财呢?其实方法也很简单:

1.确定自己希望获得财务上的成功。 2.自信,有想法,做自己喜欢做的事。 3.把钱分成日常开销、梦想目标和金鹅账户三部分。 4.进行明智的投资。 5.享受生活。

其中我想谈谈第三点和第四点,将自己的收入分成几部分,日常开销用于日常花销,梦想目标用于实现梦想的财富,金鹅账户则是养成为我们下“金蛋”的金鹅。将收入偏向任何一个部分都是不合理的,收入不可以只顾眼前,也不可以全部存起来,对于有债务的人们来说更不可以全部用来还债。

理财的最后一步我认为尤为重要,钱是用来花的,理财是为了更好的消费和生活,因此无论何时都别忘了享受当下,享受金钱带来便利的同时,学会控制和使用。这是一生都要学习并会因此受益的功课。

《小狗钱钱》这本书是作者博多·舍费尔于2002年出版的书籍,虽时间已久但这本书带给人的启发还是不小,作者的新作《财富自由之路》也已经出到第三版了,希望大家能从书中汲取智慧,并过的越来越好。

有一些读这本书的人听不列你说的话,于是就没有任何改变。另一些人读过之后开始聪明地理财,他们会拥有更幸福更富有的生活。

当你开始行动,一切都会变得不一样,愿你的生活越来越好。

一种C程序使用IPC多进程共享内存并实现热迁移的方法

在软件中,术语共享内存指可被多个进程存取的内存,一个进程是一段程序的单个运行实例。在这种情况下,共享内存被用作进程间的通讯。——WikiPedia

在Linux系统中,有多种C语言支持的共享内存使用方法,包括以下几种:

  1. 基于传统 SYS V 的共享内存;
  2. 基于 POSIX mmap 文件映射实现共享内存;
  3. 通过 memfd_create()fd 跨进程共享实现共享内存;
  4. 多媒体、图形领域广泛使用的基于 dma-buf 的共享内存。

CRIU 是用于 Linux 操作系统的软件工具。使用此工具,可以冻结正在运行的应用程序,并将其作为文件集合检查点到持久性存储中。然后,人们可以使用这些文件从冻结点还原并运行应用程序。但不是所有程序都支持通过CRIU进行热迁移,例如使用了 SYS V 的C程序就不可以使用 CRIU 进行 进程热迁移。

这篇文章讨论如何使用CRIU迁移使用了共享内存的程序,主要讨论其中的前两种共享内存方法,最终介绍一种支持热迁移的C程序共享内存使用方法

共享简单实现

System V ,曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支, SYS V 共享内存历史悠久、年代久远、API怪异,对应内核代码 linux/ipc/shm.c ,使用命令 ipcs 看到的就是这种内存; Posix 表示可移植操作系统接口(Portable Operating System Interface ,缩写为 POSIX ),POSIX标准定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种 UNIX 操作系统上运行的软件而定义的一系列API标准的总称,其正式称呼为IEEE 1003,而国际标准名称为ISO/IEC 9945。

下面列举了两种共享内存的C程序使用方法。

(1)Sys V 共享内存

ipc_share_mem_write ,共享内存写入示例程序。

/*************************************************************************
    > File Name : ipc_share_mem_write.c
    > Author : TL Song
    > EMail : songtianlun@frytea.com
    > Created Time : Wed 30 Dec 2020 03:17:00 PM CST
 ************************************************************************/

#include <stdio.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char ** argv)
{
    key_t key = ftok("/dev/shm/myshm2",0);
    int shm_id = shmget(key, 0x400000, IPC_CREAT | 0666);
    char *p = (char *)shmat(shm_id, NULL, 0);
    char cIndex = 'A';
    int i = 0;
    for(i=0;i<100;i++){
        memset(p, cIndex++, 0x400000);
        printf("Write '%c' to mem '%p'\n", *p, p);
        sleep(1);
    }
    shmdt(p);
    return 0;
}

ipc_share_mem_read ,共享读取示例程序。

/*************************************************************************
    > File Name : ipc_share_mem_read.c
    > Author : TL Song
    > EMail : songtianlun@frytea.com
    > Created Time : Wed 30 Dec 2020 03:22:20 PM CST
 ************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>

int main(int argc, char ** argv)
{
    key_t key = ftok("/dev/shm/myshm2", 0);
    int shm_id = shmget(key, 0x400000, 0666);
    char *p = (char *)shmat(shm_id, NULL, 0);
    int i = 0;
    for(i = 0 ;i < 100; i++)
    {
        printf("Read '%c' in mem '%p'\n", *p, p);
        sleep(1);
    }
    shmdt(p);
    return 0;
}

直接编译运行即可:

$ gcc ipc_share_mem_write.c -o ipc_share_mem_write
$ gcc ipc_share_mem_read.c -o ipc_share_mem_read
$ touch /dev/shm/myshm2

# 在两个终端分别执行程序即可。

可以使用 free 命令查看执行前后共享内存空间的变化情况:

[root@criu_go ~]# free
              total        used        free      shared  buff/cache   available
Mem:        3880732     3193512      421660        9216      265560      461624
Swap:       4063228           0     4063228
[root@criu_go ~]# free
              total        used        free      shared  buff/cache   available
Mem:        3880732     3193744      417308       13312      269680      457292

(2)POSIX 共享内存

ipc_share_mem_posix_write ,共享内存写入示例程序。

/*************************************************************************
    > File Name : ipc_share_mem_posix_write.c
    > Author : TL Song
    > EMail : songtianlun@frytea.com
    > Created Time : Wed 30 Dec 2020 03:17:00 PM CST
 ************************************************************************/

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    int fd = shm_open("posixsm", O_CREAT | O_RDWR, 0666);
    ftruncate(fd, 0x400000);

    char *p = mmap(NULL, 0x400000, PROT_READ| PROT_WRITE, MAP_SHARED, fd, 0);
    char cIndex = 'A';
    int i = 0;
    for(i=0;i<100;i++){
        memset(p, cIndex++, 0x400000);
        printf("Write '%c' to mem '%p'\n", *p, p);
        sleep(1);
    }
    munmap(p, 0x400000);
    return 0;
}

ipc_share_mem_posix_read ,共享读取示例程序。

/*************************************************************************
    > File Name : ipc_share_mem_posix_read.c
    > Author : TL Song
    > EMail : songtianlun@frytea.com
    > Created Time : Wed 30 Dec 2020 03:22:20 PM CST
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char ** argv)
{
    int fd = shm_open("posixsm", O_RDONLY, 0666);
    ftruncate(fd, 0x400000);

    char *p = mmap(NULL, 0x400000, PROT_READ, MAP_SHARED, fd, 0);
    int i = 0;
    for(i = 0 ;i < 100; i++)
    {
        printf("Read '%c' in mem '%p'\n", *p, p);
        sleep(1);
    }
    munmap(p, 0x400000);
    return 0;
}

直接编译运行即可:

$ gcc ipc_share_mem_posix_write.c -o ipc_share_mem_posix_write -lrt
$ gcc ipc_share_mem_posix_read.c -o ipc_share_mem_posix_read -lrt

# 在两个终端分别执行程序即可。

之后可以在 /dev/shm//run/shm 下面看到一个文件。

进程热迁移

上文简单提到了 criu 工具,本文的目标即迁移使用了共享内存的C程序,实测使用了 Sys V 共享内存的C程序无法迁移,报错如下:

Task 4526 with SysVIPC shmem map @7fdff5956000 doesn't live in IPC ns

使用POSIX mmap 文件映射实现共享内存的C程序可以使用 criu 实现进程热迁移,只需迁移共享内存文件及相关程序和文件即可实现本机和跨主机间的进程迁移,前提是内核、criu版本保持一致。迁移方法很简单,至于criu的安装,使用以下命令安装即可。

$ yum install criu -y 
$ criu check
Looks good.

CLI 进行进程迁移

# 获取进程 PID
$ ps -ef | grep ipc
root     15748 15340  0 10:56 pts/1    00:00:00 ./checkpoint_demo
root     15751 15479  0 10:56 pts/2    00:00:00 grep --color=auto checkpoint_demo

# 对进程打快照
$ criu dump -D ./migrate_imgs/ -j -t 15748

# 略去拷贝快照文件夹的步骤,自行拷贝至目标机器任意位置即可

# 拷贝共享内存文件至目标位置
$ scp /dev/shm/posixsm root@192.168.7.48:/dev/shm/posixsm 

# 拷贝程序文件至目标位置,注意迁移前后的程序和依赖文件的路径必须保持一致
$ scp PracticeDev/clang/ipc_test/ipc_share_mem_posix_write root@192.168.7.48:/root/PracticeDev/clang/ipc_test

# 恢复进程状态
$ criu restore -D ./migrate_imgs/ -j

使用该方法可以将使用了共享内存的C程序冻结,之后恢复进程状态,Posix 共享内存的API略有不同,但使用方法类似,至于更进一步的探索,还需继续努力。

参考文献

Docker 热迁移探索,基于CRIU实现运行状态迁移

版本限制

  • Docker: 17.06.0-ce
  • criu: 3.12
  • kernal: 3.10.0-957.el7.x86_64 || 5.10.2-1.el7.elrepo.x86_64 (Optional)
  • os: CentOS Linux release 7.9.2009 (Core) (Optional)

实测在该环境下,容器热迁移可用,热迁移成功与否与 dockercriu 版本强相关。

环境部署


# Docker 安装
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum list docker-ce --showduplicates | sort -r
$ sudo yum install docker-ce-17.06.0.ce
$ sudo systemctl start docker

# 启动Docker实验特征
vim **/etc/docker/daemon.json
+ { "experimental": true }**

# criu 安装
$ sudo yum install criu -y

# Go安装(可选)
wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.15.6.linux-amd64.tar.gz
vim /etc/profile
+ export PATH=$PATH:/usr/local/go/bin
source /etc/profile

热迁移示例

# On the host
$ docker run -d --name looper2 --security-opt seccomp:unconfined busybox \
         /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'

# wait a few seconds to give the container an opportunity to print a few lines, then
$ docker checkpoint create looper2 checkpoint2

# check your container & print log file
$ docker logs looper2

# On the client
$ docker create --name looper-clone --security-opt seccomp:unconfined busybox \
         /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'

$ docker start --checkpoint=checkpoint2 looper-clone

# check your container
$ docekr ps
$ docker logs looper-clone

以上步骤将容器 looper2 的状态迁移到 looper-clone ,可实现当前容器、跨容器的状态迁移,甚至可以实现跨主机的迁移,只需将该目录 /var/lib/docker/{docker id}/checnkpoints/ 下面与检查点同名的文件夹迁移即可。

附件

附件一:C测试程序

/*************************************************************************
    > File Name : fork_test.c
    > Author : TL Song
    > EMail : songtianlun@frytea.com
    > Created Time : Wed 23 Dec 2020 08:46:47 AM CST
 ************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>

int main(int arg,char* argv[]) {

    int i = 0;
    time_t t;
    struct tm *timeinfo;
    // int 被 typedef为 pid_t
    pid_t pid=fork();

    // 当pid==0时,是子进程代码运行区域。其他则是父进程运行区域。
    if(pid<0) {
        printf("Create child process failure ...\n");
    }else if(pid==0) {
        //子进程执行体
        printf("Hi i am child process ,my processId is %i \n",getpid());
        i = 0;
        while (1) {
            sleep(1);
            time(&t);
            timeinfo = localtime(&t);
            printf("Child: %d %s\n", i++, asctime(timeinfo));
            fflush(stdout);
            if(i>100)
                break;
        }
    }
    else{
        //父进程执行体
        printf("parent process is run ,myid is %i \n",getpid());
        i = 0;
        while (1) {
            sleep(1);
            time(&t);
            timeinfo = localtime(&t);
            printf("Main : %d %s\n", i++, asctime(timeinfo));
            fflush(stdout);
            if(i>100)
                break;
        }
    }
    // 执行体结束标志
    if(pid==0) {
        printf("pid=%i child process end ... \n",getpid());
    }
    else {
        // 睡眠5s,等待子先进程结束
        sleep(5);
        printf("pid=%i Parent process End ... \n",getpid());
    }

    return 0;
}

参考文献