qidao123.com技术社区-IT企服评测·应用市场

标题: IP协议、以太网包头及UNIX域套接字 [打印本页]

作者: 农民    时间: 6 天前
标题: IP协议、以太网包头及UNIX域套接字
IP协议、以太网包头及UNIX域套接字
IP包头布局
IP协议是互联网的核心协议之一,其包头包含了丰富的信息来控制数据包的传输。让我们具体解析IPv4包头布局:
最大传输单元(MTU)
MTU(Maximum Transmission Unit)是数据链路层能传输的最大数据帧巨细,默认1500字节。当IP数据包凌驾MTU时:
• 若DF标记为0,则举行分片
• 若DF标记为1,则丢弃数据包
分片规则:
• 除最后一片外,其他分片长度必须是8的整数倍
• 接收方根据标识、片偏移和MF标记重组数据
以太网包头布局
以太网是应用最广泛的局域网技能,其帧布局如下:
UNIX域套接字详解
UNIX域套接字用于同一主机上的进程间通讯(IPC),比网络套接字更高效。
流式套接字(SOCK_STREAM)
服务器端流程
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <sys/un.h>
  7. #define SOCKET_PATH "/tmp/unix_socket_example"
  8. int main() {
  9.     int server_fd, client_fd;
  10.     struct sockaddr_un addr;
  11.     char buffer[100];
  12.     // 1. 创建套接字
  13.     server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
  14.     if (server_fd == -1) {
  15.         perror("socket");
  16.         exit(EXIT_FAILURE);
  17.     }
  18.     // 2. 绑定套接字到文件系统路径
  19.     memset(&addr, 0, sizeof(struct sockaddr_un));
  20.     addr.sun_family = AF_UNIX;
  21.     strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
  22.     unlink(SOCKET_PATH); // 确保路径没有被占用
  23.     if (bind(server_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
  24.         perror("bind");
  25.         close(server_fd);
  26.         exit(EXIT_FAILURE);
  27.     }
  28.     // 3. 监听连接请求
  29.     if (listen(server_fd, 5) == -1) {
  30.         perror("listen");
  31.         close(server_fd);
  32.         exit(EXIT_FAILURE);
  33.     }
  34.     printf("服务器正在等待连接...\n");
  35.     // 4. 接受客户端连接
  36.     client_fd = accept(server_fd, NULL, NULL);
  37.     if (client_fd == -1) {
  38.         perror("accept");
  39.         close(server_fd);
  40.         exit(EXIT_FAILURE);
  41.     }
  42.     // 5. 与客户端通信
  43.     memset(buffer, 0, sizeof(buffer));
  44.     read(client_fd, buffer, sizeof(buffer));
  45.     printf("收到客户端消息: %s\n", buffer);
  46.     const char *response = "你好,客户端!";
  47.     write(client_fd, response, strlen(response) + 1);
  48.     // 6. 关闭套接字
  49.     close(client_fd);
  50.     close(server_fd);
  51.     unlink(SOCKET_PATH);
  52.     return 0;
  53. }
复制代码
客户端流程
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <sys/un.h>
  7. #define SOCKET_PATH "/tmp/unix_socket_example"
  8. int main() {
  9.     int client_fd;
  10.     struct sockaddr_un addr;
  11.     char buffer[100];
  12.     // 1. 创建套接字
  13.     client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
  14.     if (client_fd == -1) {
  15.         perror("socket");
  16.         exit(EXIT_FAILURE);
  17.     }
  18.     // 2. 连接到服务器
  19.     memset(&addr, 0, sizeof(struct sockaddr_un));
  20.     addr.sun_family = AF_UNIX;
  21.     strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
  22.     if (connect(client_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
  23.         perror("connect");
  24.         close(client_fd);
  25.         exit(EXIT_FAILURE);
  26.     }
  27.     // 3. 与服务器通信
  28.     const char *message = "你好,服务器!";
  29.     write(client_fd, message, strlen(message) + 1);
  30.     memset(buffer, 0, sizeof(buffer));
  31.     read(client_fd, buffer, sizeof(buffer));
  32.     printf("收到服务器响应: %s\n", buffer);
  33.     // 4. 关闭套接字
  34.     close(client_fd);
  35.     return 0;
  36. }
复制代码
数据报套接字(SOCK_DGRAM)
服务器端流程
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <sys/un.h>
  7. #define SOCKET_PATH "/tmp/unix_dgram_socket_example"
  8. int main() {
  9.     int sockfd;
  10.     struct sockaddr_un addr;
  11.     char buffer[100];
  12.     ssize_t num_bytes;
  13.     struct sockaddr_un client_addr;
  14.     socklen_t client_addr_len = sizeof(client_addr);
  15.     // 1. 创建套接字
  16.     sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
  17.     if (sockfd == -1) {
  18.         perror("socket");
  19.         exit(EXIT_FAILURE);
  20.     }
  21.     // 2. 绑定套接字
  22.     memset(&addr, 0, sizeof(addr));
  23.     addr.sun_family = AF_UNIX;
  24.     strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
  25.     unlink(SOCKET_PATH);
  26.     if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  27.         perror("bind");
  28.         close(sockfd);
  29.         exit(EXIT_FAILURE);
  30.     }
  31.     printf("服务器正在等待消息...\n");
  32.     // 3. 接收消息
  33.     memset(buffer, 0, sizeof(buffer));
  34.     num_bytes = recvfrom(sockfd, buffer, sizeof(buffer), 0,
  35.                         (struct sockaddr *)&client_addr, &client_addr_len);
  36.     if (num_bytes == -1) {
  37.         perror("recvfrom");
  38.         close(sockfd);
  39.         exit(EXIT_FAILURE);
  40.     }
  41.     printf("收到客户端消息: %s\n", buffer);
  42.     // 4. 发送响应
  43.     const char *response = "你好,客户端!";
  44.     if (sendto(sockfd, response, strlen(response) + 1, 0,
  45.                (struct sockaddr *)&client_addr, client_addr_len) == -1) {
  46.         perror("sendto");
  47.         close(sockfd);
  48.         exit(EXIT_FAILURE);
  49.     }
  50.     // 5. 关闭套接字
  51.     close(sockfd);
  52.     unlink(SOCKET_PATH);
  53.     return 0;
  54. }
复制代码
客户端流程
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <sys/un.h>
  7. #define SOCKET_PATH "/tmp/unix_dgram_socket_example"
  8. int main() {
  9.     int sockfd;
  10.     struct sockaddr_un server_addr;
  11.     char buffer[100];
  12.     ssize_t num_bytes;
  13.     // 1. 创建套接字
  14.     sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
  15.     if (sockfd == -1) {
  16.         perror("socket");
  17.         exit(EXIT_FAILURE);
  18.     }
  19.     // 2. 设置服务器地址
  20.     memset(&server_addr, 0, sizeof(server_addr));
  21.     server_addr.sun_family = AF_UNIX;
  22.     strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);
  23.     // 3. 发送消息
  24.     const char *message = "你好,服务器!";
  25.     if (sendto(sockfd, message, strlen(message) + 1, 0,
  26.                (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
  27.         perror("sendto");
  28.         close(sockfd);
  29.         exit(EXIT_FAILURE);
  30.     }
  31.     // 4. 接收响应
  32.     memset(buffer, 0, sizeof(buffer));
  33.     num_bytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL);
  34.     if (num_bytes == -1) {
  35.         perror("recvfrom");
  36.         close(sockfd);
  37.         exit(EXIT_FAILURE);
  38.     }
  39.     printf("收到服务器响应: %s\n", buffer);
  40.     // 5. 关闭套接字
  41.     close(sockfd);
  42.     return 0;
  43. }
复制代码
sockaddr_un布局体
  1. #include <sys/un.h>
  2. struct sockaddr_un {
  3.     sa_family_t sun_family;  // 地址族,设置为AF_UNIX
  4.     char sun_path[108];      // 文件系统路径名
  5. };
复制代码
• sun_family:必须设置为AF_UNIX
• sun_path:最大长度108字节(包罗终止符),通常以/tmp/开头
注意事项

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4