本文首发于:https://blog.frytea.com/archives/505/
Unix domain socket 或者 IPC socket是一种终端,可以使同一台操作系统上的两个或多个进程进行数据通信。提供 UDP 和 TCP 两种通信机制。
因为一些原因,项目现有软件架构采用的都是 IPC sockte
中的 TCP
通信机制,虽然保证了通信的可靠性,但近期需要对该程序进行热迁移(基于 criu
),有连接的 IPC 套接字状态很难被保存和恢复,而 无连接的 UDP 只需要保证服务端先冻结、先恢复即可实现程序整体状态迁移,因此写下本文,记录迁移过程,最后提供示例程序,可以自行通过 BCompare
等文本对比工具对比差异。
模式差异
至于两种通信机制的差异,除了在创建套接字时声明的差异,具体的通信流程也有差异,在这里找到 CSDN @frank909 的两张图片,感觉很有代表性,在这里引用一下。
首先是 TCP的:
接下来是 UDP 的:
二者的差异,主要是这几点:
- 服务端:
(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: [email protected]
> 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