AF_INET域与AF_UNIX域socket通信原理对比

一、原理对比分析

Linux 内核协议簇中有几十种通讯协议,AF-INET是我们常见 TCP/IP 的通讯方式, AF-UNIX 是用于本机线程间通讯一种IPC机制,从用户角度看,所采用通讯模式相差不大,但就原理上看,相差较大。

1. AF_INET域socket通信过程

在这里插入图片描述
典型的TCP/IP四层模型的通信过程。

发送方、接收方依赖IP:Port来标识,即将本地的socket绑定到对应的IP端口上,发送数据时,指定对方的IP端口,经过Internet,可以根据此IP端口最终找到接收方;接收数据时,可以从数据包中获取到发送方的IP端口。

发送方通过系统调用send()将原始数据发送到操作系统内核缓冲区中。内核缓冲区从上到下依次经过TCP层、IP层、链路层的编码,分别添加对应的头部信息,经过网卡将一个数据包发送到网络中。经过网络路由到接收方的网卡。网卡通过系统中断将数据包通知到接收方的操作系统,再沿着发送方编码的反方向进行解码,即依次经过链路层、IP层、TCP层去除头部、检查校验等,最终将原始数据上报到接收方进程。

2. AF_UNIX域socket通信过程

典型的本地IPC,类似于管道,依赖路径名标识发送方和接收方。即发送数据时,指定接收方绑定的路径名,操作系统根据该路径名可以直接找到对应的接收方,并将原始数据直接拷贝到接收方的内核缓冲区中,并上报给接收方进程进行处理。同样的接收方可以从收到的数据包中获取到发送方的路径名,并通过此路径名向其发送数据。
在这里插入图片描述

3. 相同点

操作系统提供的接口socket(),bind(),connect(),accept(),send(),recv(),以及用来对其进行多路复用事件检测的select(),poll(),epoll()都是完全相同的。收发数据的过程中,上层应用感知不到底层的差别。

4. 不同点

  • 1 建立socket传递的地址域,及bind()的地址结构稍有区别:

socket() 分别传递不同的域AF_INET和AF_UNIX

bind()的地址结构分别为sockaddr_in(制定IP端口)和sockaddr_un(指定路径名)

  • 2 AF_INET需经过多个协议层的编解码,消耗系统cpu,并且数据传输需要经过网卡,受到网卡带宽的限制。AF_UNIX数据到达内核缓冲区后,由内核根据指定路径名找到接收方socket对应的内核缓冲区,直接将数据拷贝过去,不经过协议层编解码,节省系统cpu,并且不经过网卡,因此不受网卡带宽的限制。

  • 3 AF_UNIX的传输速率远远大于AF_INET

  • 4 AF_INET不仅可以用作本机的跨进程通信,同样的可以用于不同机器之间的通信,其就是为了在不同机器之间进行网络互联传递数据而生。而AF_UNIX则只能用于本机内进程之间的通信。

5. 使用场景

AF_UNIX由于其对系统cpu的较少消耗,不受限于网卡带宽,及高效的传递速率,本机通信则首选AF_UNIX域。
不用多说,AF_INET则用于跨机器之间的通信。

二、附录 AF-UNIX 使用样例

客户端程序

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/un.h>

int main()
{
    /* 创建一个socket */
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    
    struct sockaddr_un address;
    address.sun_family = AF_UNIX;
    strcpy(address.sun_path, "server_socket");
    
    /*从键盘读取需要转置的整数*/
    int num;
    printf("Please enter the num to reverse:\n");

    /* 链接至服务端 */
    int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
    if(result == -1)
    {
        perror("connect failed: ");
        exit(1);
    }
    
    /* 数据处理 */
    write(sockfd, &num, 4);//一个int 4个字节
    read(sockfd, &num, 4);
    printf("get an integer from server: %d\n", num);
    
    /* 关闭socket */
    close(sockfd);
    
    return 0;
}  

服务器端程序

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/un.h> //define the sockaddr_un structure

int num_reverse(int num);

int main()
{
    /* 断开之前的socket文件 */
    unlink("server_socket");
    
    /* 创建一个socket */
    int server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    
    struct sockaddr_un server_addr;
    server_addr.sun_family = AF_UNIX;
    strcpy(server_addr.sun_path, "server_socket");
    
    /* 与本地文件进行绑定 */
    bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    
    /* 监听 */
    if(listen(server_sockfd, 5)<0);
    {
	    perror("Listen failed");
    }
    
    int client_sockfd;
    struct sockaddr_un client_addr;
    socklen_t len = sizeof(client_addr);
    
    while(1)
    {
        printf("server waiting:\n");
        /* 接受一个客户端的链接 */
        client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);
        
        /*数据交换 */
        read(client_sockfd, &num, 4);
        printf("get an integer from client: %d\n", num);
        num=num_reverse(num);
        write(client_sockfd, &num, 4);
        
        /* 关闭socket */
        close(client_sockfd);
    }
    
    return 0;
}

	int num_reverse(int num)
	{
	    int S=0,sum=0;
	    
	    while(num)
	    {
	        S=num%10;
	        sum=10*sum+S;
	        num = num / 10;
	    }
	    
	    return sum;
	}

此程序仅供学习参考。

参考链接
https://blog.csdn.net/w710537643/article/details/112582731
https://blog.csdn.net/weixin_39258979/article/details/80931464

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值