• lv7 嵌入式开发-网络编程开发 13 UNIX域套接字


    目录

    1 UNIX 域流式套接字

    2 UNIX 域数据报套接字


    1 UNIX 域流式套接字

    UNIX 域流式套接字(UNIX domain stream socket)是一种在同一台主机上的进程之间进行通信的机制。它不依赖于网络协议栈,而是使用文件系统作为通信的基础。

    UNIX 域流式套接字提供可靠的、双向的、面向连接的通信方式。与传统的套接字不同,UNIX 域套接字不需要经过网络协议栈,数据直接通过内核中的缓冲区进行传递,因此具有低延迟和高效率的特点。

    UNIX 域流式套接字广泛用于本地进程之间的通信,例如在同一台服务器上的多个进程之间共享数据、同步操作等。它是一种高效、可靠的 IPC(进程间通信)机制。

    本地地址

    1. struct sockaddr_un {
    2. unsigned short sun_family; /* 协议类型 */
    3. char sun_path[108]; /* 套接字文件路径 */
    4. };

    UNIX 域流式套接字的用法和 TCP 套接字基本一致,区别在于使用的协议和地址不同

    UNIX 域流式套接字服务器端流程如下:

    (1)创建 UNIX 域流式套接字。

    (2)绑定本地地址(套接字文件)。

    (3)设置监听模式。

    (4)接收客户端的连接请求。

    (5)发送/接收数据。

    补充:在linux中输入man bind,下方有流套接字示例代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define MY_SOCK_PATH "/tmp/my_sock_file"
    8. #define LISTEN_BACKLOG 50
    9. #define handle_error(msg) \
    10. do { perror(msg); exit(EXIT_FAILURE); } while (0)
    11. int main(int argc, char *argv[])
    12. {
    13. int sfd, cfd;
    14. struct sockaddr_un my_addr, peer_addr;
    15. socklen_t peer_addr_size;
    16. char buf[BUFSIZ] = {};
    17. sfd = socket(AF_UNIX, SOCK_STREAM, 0);
    18. if (sfd == -1)
    19. handle_error("socket");
    20. memset(&my_addr, 0, sizeof(struct sockaddr_un));
    21. my_addr.sun_family = AF_UNIX;
    22. strncpy(my_addr.sun_path, MY_SOCK_PATH,
    23. sizeof(my_addr.sun_path) - 1);
    24. if (bind(sfd, (struct sockaddr *) &my_addr,
    25. sizeof(struct sockaddr_un)) == -1)
    26. handle_error("bind");
    27. if (listen(sfd, LISTEN_BACKLOG) == -1)
    28. handle_error("listen");
    29. peer_addr_size = sizeof(struct sockaddr_un);
    30. cfd = accept(sfd, (struct sockaddr *) &peer_addr,
    31. &peer_addr_size);
    32. if (cfd == -1)
    33. handle_error("accept");
    34. recv(cfd, buf, BUFSIZ, 0);
    35. printf("%s\n", buf);
    36. close(cfd);
    37. close(sfd);
    38. //不删除文件,下次打开会出错
    39. remove(MY_SOCK_PATH);
    40. return 0;
    41. }

    UNIX 域流式套接字客户端流程如下。

    (1)创建 UNIX 域流式套接字。

    (2)指定服务器端地址(套接字文件)。

    (3)建立连接。

    (4)发送/接收数据。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define MY_SOCK_PATH "/tmp/my_sock_file"
    8. #define handle_error(msg) \
    9. do { perror(msg); exit(EXIT_FAILURE); } while (0)
    10. int main(int argc, char *argv[])
    11. {
    12. int fd;
    13. struct sockaddr_un peer_addr;
    14. char buf[BUFSIZ] = {"Hello World!"};
    15. fd = socket(AF_UNIX, SOCK_STREAM, 0);
    16. if (fd == -1)
    17. handle_error("socket");
    18. memset(&peer_addr, 0, sizeof(struct sockaddr_un));
    19. peer_addr.sun_family = AF_UNIX;
    20. strncpy(peer_addr.sun_path, MY_SOCK_PATH,
    21. sizeof(peer_addr.sun_path) - 1);
    22. if (connect(fd, (struct sockaddr *) &peer_addr,
    23. sizeof(struct sockaddr_un)) == -1)
    24. handle_error("connect");
    25. printf("%s\n",buf);
    26. send(fd, buf, strlen(buf), 0);
    27. close(fd);
    28. return 0;
    29. }

    2 UNIX 域数据报套接字

    UNIX 域数据套接字(UNIX domain datagram socket)是一种在同一台主机上的进程之间进行通信的机制。类似于UNIX 域流式套接字,UNIX 域数据套接字也不依赖于网络协议栈,而是使用文件系统作为通信的基础。

    UNIX 域数据套接字提供无连接的、不可靠的通信方式。它使用数据报(datagram)进行通信,每个数据报都是独立的、自包含的消息单元。与UNIX 域流式套接字不同,UNIX 域数据套接字不需要建立连接,数据可以直接发送和接收。

    UNIX 域数据套接字适用于面向消息的通信模式,可以用于实现进程间的异步通信,发送和接收各种类型的消息,如命令、状态信息等。它也常用于本地进程间的通信,特别是在需要高效、低延迟的情况下。与UNIX 域流式套接字相比,UNIX 域数据套接字在功能上更为简单,但传输效率更高。

    UNIX 域用户数据报套接字的流程可参考 UDP 套接字

    UNIX 域流式套接字服务器端流程如下:

    (1)创建 UNIX 域流式套接字。

    (2)绑定本地地址(套接字文件)。

    (3)发送/接收数据。

    服务端

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define MY_SOCK_PATH "/tmp/my_sock_file"
    8. #define handle_error(msg) \
    9. do { perror(msg); exit(EXIT_FAILURE); } while (0)
    10. int main(int argc, char *argv[])
    11. {
    12. int fd;
    13. struct sockaddr_un my_addr, peer_addr;
    14. socklen_t peer_addr_size;
    15. char buf[BUFSIZ] = {};
    16. fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    17. if (fd == -1)
    18. handle_error("socket");
    19. memset(&my_addr, 0, sizeof(struct sockaddr_un));
    20. my_addr.sun_family = AF_UNIX;
    21. strncpy(my_addr.sun_path, MY_SOCK_PATH,
    22. sizeof(my_addr.sun_path) - 1);
    23. if (bind(fd, (struct sockaddr *) &my_addr,
    24. sizeof(struct sockaddr_un)) == -1)
    25. handle_error("bind");
    26. peer_addr_size = sizeof(struct sockaddr_un);
    27. recvfrom(fd, buf, BUFSIZ, 0, (struct sockaddr *) &peer_addr,
    28. &peer_addr_size);
    29. printf("%s\n",buf);
    30. close(fd);
    31. //不删除文件下次打开会出错
    32. remove(MY_SOCK_PATH);
    33. return 0;
    34. }

    客户端 

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define MY_SOCK_PATH "/tmp/my_sock_file"
    8. #define handle_error(msg) \
    9. do { perror(msg); exit(EXIT_FAILURE); } while (0)
    10. int main(int argc, char *argv[])
    11. {
    12. int fd;
    13. struct sockaddr_un peer_addr;
    14. socklen_t peer_addr_size;
    15. char buf[BUFSIZ] = {"Hello World!"};
    16. fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    17. if (fd == -1)
    18. handle_error("socket");
    19. memset(&peer_addr, 0, sizeof(struct sockaddr_un));
    20. peer_addr.sun_family = AF_UNIX;
    21. strncpy(peer_addr.sun_path, MY_SOCK_PATH,
    22. sizeof(peer_addr.sun_path) - 1);
    23. peer_addr_size = sizeof(struct sockaddr_un);
    24. printf("%s\n", buf);
    25. sendto(fd, buf, strlen(buf), 0, (struct sockaddr *) &peer_addr,
    26. peer_addr_size);
    27. close(fd);
    28. //不删除文件下次打开会出错
    29. remove(MY_SOCK_PATH);
    30. return 0;
    31. }

  • 相关阅读:
    无视Win11 TPM/英特尔芯片等配置,强制升级Win11
    【布局优化】基于粒子群算法求解集线器位置分配问题附matlab代码
    使用gson将复杂的树型结构转Json遇到的问题,写入文件为空
    windows docke下载mysql并且配置远程访问
    k8s--基础--01--介绍
    轻松拿捏C语言——【文件操作】
    springboot项目开发实战
    第十五章 汇编语言与逆向编程
    angular ag-grid api
    一本书,带你走出Spring新手村
  • 原文地址:https://blog.csdn.net/m0_60718520/article/details/133607264