开发者社区> xcywt> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

UNIX域协议(命名套接字)

简介: 这里主要介绍命名UNIX域套接字 1.什么是UNIX域套接字Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务通信的一种方式。是进程间通信(IPC)的一种方式。它提供了两类套接字:字节流套接字(有点像TCP)和数据报套接字(有点像UDP)UNIX域数据报服务是可靠的,不会丢失消息,也不会传递出错。
+关注继续查看

 

这里主要介绍命名UNIX域套接字

1.什么是UNIX域套接字
Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务通信的一种方式。是进程间通信(IPC)的一种方式。
它提供了两类套接字:字节流套接字(有点像TCP)和数据报套接字(有点像UDP)
UNIX域数据报服务是可靠的,不会丢失消息,也不会传递出错。

IP协议标识客户服务器是通过IP地址和端口号实现的,UNIX域协议中用于标识客户机和服务器的协议地址的是普通文件系统中的路径名。

2.UNIX域协议特点
1)UNIX域套接字域TCP套接字相比,在同一台主机的传输速度前者是后者的两倍。UNIX域套接字仅仅复制数据,并不执行协议处理,不需要添加或删除网络报头,无需计算校验和,不产生顺序号,也不需要发送确认报文
2)UNIX域套接字可以在同一台主机上各进程之间传递文件描述符
3)UNIX域套接字域传统套接字的区别是用路径名表示协议族的描述

3.UNIX域地址结构

#define UNIX_PATH_MAX 128
struct sockaddr_un{
sa_family_t sun_family; /* AF_UNIX 或者 AF_LOCAL */
char sun_path[UNIX_PATH_MAX]; /* path name */
};

 

4.使用实例,编程套路跟TCP很像。
Server:先创建套接字 -> 绑定地址 -> 监听 -> accept 客户端连接 -> 连接成功开始通信 -> 关闭套接字
Client:先创建套接字 -> 连接server -> 开始通信 -> 关闭套接字。
这里实现一个简单的回射服务器。
启动服务器,等待客户端连接,连接上之后,客户端通过标准输入接收数据发送给服务器。服务器接收数据以后,再把数据发送回客户端。
下面上代码:

server:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/un.h>
//#include<netinet/in.h>
#define ERR_EXIT(m) \
    do \
    { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)
#define UNIXSOCKETNAME "test_socket"
void echo_cli(int sock)
{
    char buf[1024] = {0};
    int ret = 0;
    while(1)
    {
        ret = read(sock, buf, sizeof(buf));
        if(ret == 0)
        {
            printf("client %d close\n", sock);
            break;
        }
        
        write(sock, buf, strlen(buf));
    }
    close(sock);
}
int main()
{
    int listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(listenfd < 0)
        ERR_EXIT("socket");
    unlink(UNIXSOCKETNAME);
    struct sockaddr_un servaddr;  // 头文件是这个 #include <sys/un.h>
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, UNIXSOCKETNAME);
    if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
        ERR_EXIT("bind");
    if(listen(listenfd, SOMAXCONN) < 0)
        ERR_EXIT("listen");
    int conn = 0;
    pid_t pid;
    while(1)
    {
        conn = accept(listenfd, NULL, NULL);
        if(conn == -1)
        {
            if(errno == EINTR)
                continue;
            ERR_EXIT("accept");
        }
        printf("Has new client connected, conn = %d\n", conn);
        pid = fork();
        if(pid < 0)
            ERR_EXIT("fork");
        else if(pid == 0)
        {            
            echo_cli(conn);
            exit(1);
        }
        else
            close(conn);
    }
    return 0;
}

client:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/un.h>
//#include<netinet/in.h>
#define UNIXSOCKETNAME "test_socket"
#define ERR_EXIT(m) \
    do \
    { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)
void echo_cli(int sock)
{
    char buf1[1024] = {0};
    char buf2[1024] = {0};
    int ret = 0;
    while(fgets(buf1, sizeof(buf1), stdin) != NULL)
    {
        write(sock, buf1, strlen(buf1));
        ret = read(sock, buf2, sizeof(buf2));
        if(ret == 0)
        {
            printf("server %d close\n", sock);
            break;
        }
        printf("%s", buf2);
        memset(buf1, 0, sizeof(buf1));
        memset(buf2, 0, sizeof(buf2));
    }
    close(sock);
}
int main()
{
    int sock = socket(PF_UNIX, SOCK_STREAM, 0);
    if(sock < 0)
        ERR_EXIT("socket");
    struct sockaddr_un servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, UNIXSOCKETNAME);
    if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
        ERR_EXIT("connect");
    echo_cli(sock);
    return 0;
}

 运行:
直接gcc编译,就可以运行了。先启动server,再启动client。
注意:
1)启动server后,bind后会在对应目录创建一个文件(权限是0777&~umask)。这文件的类型是s。表示是套接口文件。可以通过ls -al查看。

srwxrwxr-x  1 xcy xcy     0  1月  3 10:29 test_socket

2)若套接口文件存在,则bind会出错。为此可以先把该文件删掉。(server中的unlink就干这个的)
3)创建的套接口文件最好为绝对路径。建议指定在/tmp目录下。比如把上面的目录改成/tmp/test_socket
3)UNIX域流式套接字connect发现监听队列满时,会立刻返回一个ECONNREFUSED,这和TCP不同,如果监听队列满了,会忽略到来的SYN,这会导致对方重传SYN。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
unix网络编程str_cli使用epoll实现
unix网络编程str_cli使用epoll实现 unix环境高级编程中也有这个函数,都是为了讲解IO多路转接。从本质上来看epoll就是一个改善了的select和poll,本质没发生任何变化,对于构建在poll,select和epoll上的框架使用者来说,没什么区别。
470 0
Unix编程/应用问答中文版 ---6./etc/system可调资源限制
发信人: dean (叮叮当当), 信区: LinuxDev标  题: Unix编程/应用问答中文版 ---6./etc/system可调资源发信站: 飘渺水云间 (Fri Nov 22 12:02:19 2002), 转信Unix编程/应用问答中文版 ---6.
514 0
UNIX 域数据报套接字
UNIX 域数据报套接字
0 0
UNIX域协议(无名套接字)
关于什么是UNIX域套接字可以参考:http://www.cnblogs.com/xcywt/p/8185597.html这里主要介绍非命名的UNIX域套接字的用法。1.socketpair函数先看man手册: SYNOPSIS       #include           /* See ...
664 0
+关注
xcywt
C++ 机器人行业
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载