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。

原文地址:https://www.cnblogs.com/xcywt/p/8185597.html

时间: 2024-11-17 12:33:02

UNIX域协议(命名套接字)的相关文章

Socket编程实践(14) --UNIX域协议

UNIX域协议 UNIX域套接字与TCP相比, 在同一台主机上, UNIX域套接字更有效率, 几乎是TCP的两倍(由于UNIX域套接字不需要经过网络协议栈,不需要打包/拆包,计算校验和,维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程, 而且UNIX域协议机制本质上就是可靠的通讯, 而网络协议是为不可靠的通讯设计的). UNIX域套接字可以在同一台主机上各进程之间传递文件描述符; UNIX域套接字与传统套接字的区别是用路径名来表示协议族的描述; UNIX域套接字也提供面向流和面向数据

【UNIX网络编程】套接字编程简介

IPv4套接字地址结构: 通常也被成为“网际套接字地址结构”,以sockaddr_in命名,定义在<netinet/in.h>头文件中. struct in_addr { in_addr_t s_addr; // 32bits的ip地址,如0xFF000001 -> 127.0.0.1 }; /* Structure describing an Internet socket address. */ struct sockaddr_in { uint8_t sin_len; /* len

UNP学习笔记(第十五章 UNIX域协议)

UNIX域协议是在单个主机上执行客户/服务器通信的一种方法 使用UNIX域套接字有以下3个理由: 1.UNIX域套接字往往比通信两端位于同一个主机的TCP套接字快出一倍 2.UNIX域套接字可用于在同一个主机上的不同进程之间传递描述符 3.UNIX域套接字较新的实现把客户的凭证提供给服务器,从而能够提供额外的安全检查措施 UNIX域中用于标识客户和服务器的协议地址是普通文件系统的路径名.这些路径名不是普通的UNIX文件: 除非他们和UNIX域套接字关联起来,否则无法读写这些文件. 可以查看之前a

LINUX学习:UNIX域协议

前言介绍: 1.UNIX域套接字与TCP套接字相比较,在同一台主机的传输四度前者是后者的两倍 2.UNIX域套接字可以在同一台主机上各进程间传递描述符 3.UNIX域套接字与传统套接字的区别是用路径名来表示协议族的描述.   UNIX域地址结构 #define UNIX_PATH_MAX 108 struct sockaddr_un{ sa_family_t sun_family; /* AF_UNIX*/ char sun_path[UNIX_PATH_MAX]; /*pathname*/ }

一起talk C栗子吧(第一百五十八回:C语言实例--基于AF_INET域的流套接字通信)

各位看官们,大家好,上一回中咱们说的是基于AF_UNIX域的数据报套接字通信的例子,这一回咱们说的例子是:基于AF_INET域的流套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回中一起制作了我们的第二道佳肴是:基于AF_UNIX域的数据报套接字通信.今天,我将和大家一起制作第三道佳肴:基于AF_INET域的流套接字通信. 制作第三道佳肴的菜谱:流套接字过程. 制作第三道佳肴的食材:流套接字的接口,套接字属性,套接字地址信息. 看官们,以上的内容,我们在前面章

一起talk C栗子吧(第一百五十九回:C语言实例--基于AF_INET域的数据报套接字通信)

各位看官们,大家好,上一回中咱们说的是基于AF_INET域的流套接字通信的例子,这一回咱们说的例子是:基于AF_INET域的数据报套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回中一起制作了我们的第三道佳肴是:基于AF_INET域的流套接字通信.今天,我将和大家一起制作第四道佳肴:基于AF_INET域的数据报套接字通信. 制作第四道佳肴的菜谱:数据报套接字过程. 制作第四道佳肴的食材:数据报套接字的接口,套接字属性,套接字地址信息. 看官们,以上的内容,我们

一起talk C栗子吧(第一百五十七回:C语言实例--基于AF_UNIX域的数据报套接字通信)

各位看官们,大家好,上一回中咱们说的是基于AF_UNIX域的流套接字通信的例子,这一回咱们说的例子是:基于AF_UNIX域的数据报套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回中一起制作了我们的第一道佳肴是:基于AF_UNIX域的流套接字通信.今天,我将和大家一起制作第二道佳肴:基于AF_UNIX域的数据报套接字通信. 制作第二道佳肴的菜谱:数据报套接字过程. 制作第二道佳肴的食材:数据报套接字的接口,套接字属性,套接字地址信息. 看官们,以上的内容,我们

一起talk C栗子吧(第一百五十六回:C语言实例--基于AF_UNIX域的流套接字通信)

各位看官们,大家好,上一回中咱们说的获取socket通信地址的例子,这一回咱们说的例子是:基于AF_UNIX域的流套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在前面章回中介绍了套接字的通信过程以及套接字的的细节,总感觉还缺少些什么,一时还真是想不起来.这好比我们有了食谱也有了食材,那么我们就可以做一道美味的佳肴了.啊!有了.一提到美味的佳肴,灵感就来了.我们缺少的是对套接字的综合演练,也就是把前面章回中知识串在一起,然后举一个综合使用套接字知识进行套接字通信的例

UNIX域协议

echocli.c #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \ do \ { \ p