一、UNIX 域流式套接字
本地地址
struct sockaddr_un {
unsigned short sun_family; /* 协议类型 */
char sun_path[108]; /* 套接字文件路径 */
};
UNIX 域流式套接字的用法和 TCP 套接字基本一致,区别在于使用的协议和地址不同
UNIX 域流式套接字服务器端流程如下:
(1)创建 UNIX 域流式套接字。
(2)绑定本地地址(套接字文件)。
(3)设置监听模式。
(4)接收客户端的连接请求。
(5)发送/接收数据。
UNIX 域流式套接字客户端流程如下。
(1)创建 UNIX 域流式套接字。
(2)指定服务器端地址(套接字文件)。
(3)建立连接。
(4)发送/接收数据。
UNIX 域用户数据报套接字的流程可参考 UDP 套接字
UNIX 域流式套接字服务器端流程如下:
(1)创建 UNIX 域流式套接字。
(2)绑定本地地址(套接字文件)。
(3)发送/接收数据。
二、UNIX域流式套接字实现
服务端
cpp
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MY_SOCK_PATH "/tmp/my_sock_file"
#define LISTEN_BACKLOG 50
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
int sfd, cfd;
struct sockaddr_un my_addr, peer_addr;
socklen_t peer_addr_size;
char buf[BUFSIZ] = {};
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1)
handle_error("socket");
memset(&my_addr, 0, sizeof(struct sockaddr_un));
my_addr.sun_family = AF_UNIX;
strncpy(my_addr.sun_path, MY_SOCK_PATH,
sizeof(my_addr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr_un)) == -1)
handle_error("bind");
if (listen(sfd, LISTEN_BACKLOG) == -1)
handle_error("listen");
peer_addr_size = sizeof(struct sockaddr_un);
cfd = accept(sfd, (struct sockaddr *) &peer_addr,
&peer_addr_size);
if (cfd == -1)
handle_error("accept");
recv(cfd, buf, BUFSIZ, 0);
printf("%s\n", buf);
close(cfd);
close(sfd);
remove(MY_SOCK_PATH);
return 0;
}
客户端
cpp
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MY_SOCK_PATH "/tmp/my_sock_file"
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
int fd;
struct sockaddr_un peer_addr;
char buf[BUFSIZ] = {"Hello World!"};
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
handle_error("socket");
memset(&peer_addr, 0, sizeof(struct sockaddr_un));
peer_addr.sun_family = AF_UNIX;
strncpy(peer_addr.sun_path, MY_SOCK_PATH,
sizeof(peer_addr.sun_path) - 1);
if (connect(fd, (struct sockaddr *) &peer_addr,
sizeof(struct sockaddr_un)) == -1)
handle_error("connect");
printf("%s\n",buf);
send(fd, buf, strlen(buf), 0);
close(fd);
return 0;
}
三、UNIX域数据报套接字实现
服务端
cpp
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MY_SOCK_PATH "/tmp/my_sock_file"
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
int fd;
struct sockaddr_un my_addr, peer_addr;
socklen_t peer_addr_size;
char buf[BUFSIZ] = {};
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd == -1)
handle_error("socket");
memset(&my_addr, 0, sizeof(struct sockaddr_un));
my_addr.sun_family = AF_UNIX;
strncpy(my_addr.sun_path, MY_SOCK_PATH,
sizeof(my_addr.sun_path) - 1);
if (bind(fd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr_un)) == -1)
handle_error("bind");
peer_addr_size = sizeof(struct sockaddr_un);
recvfrom(fd, buf, BUFSIZ, 0, (struct sockaddr *) &peer_addr,
&peer_addr_size);
printf("%s\n",buf);
close(fd);
remove(MY_SOCK_PATH);
return 0;
}
客户端
cpp
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MY_SOCK_PATH "/tmp/my_sock_file"
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
int fd;
struct sockaddr_un peer_addr;
socklen_t peer_addr_size;
char buf[BUFSIZ] = {"Hello World!"};
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd == -1)
handle_error("socket");
memset(&peer_addr, 0, sizeof(struct sockaddr_un));
peer_addr.sun_family = AF_UNIX;
strncpy(peer_addr.sun_path, MY_SOCK_PATH,
sizeof(peer_addr.sun_path) - 1);
peer_addr_size = sizeof(struct sockaddr_un);
printf("%s\n", buf);
sendto(fd, buf, strlen(buf), 0, (struct sockaddr *) &peer_addr,
peer_addr_size);
close(fd);
remove(MY_SOCK_PATH);
return 0;
}