`
kavy
  • 浏览: 888572 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Unix域套接字

 
阅读更多

原文地址:Unix域套接字 作者:tuyer

 

    管道由于只能实现具有亲缘进程的进程间通信,使用受到了很大的限制,命名管道解决了这一问题。但是,无论是管道还是命名管道,都只能实现单向通信(在只创建一个管道的情况下)。

 

使用套接字除了可以实现网络间不同主机间的通信外,还可以实现同一主机的不同进程间的通信,且建立的通信是双向的通信。这里所指的使用套接字实现进程间通信,是由将通信域指定为PF_UNIX来实现的。该函数的形式如下:

int socket(int domain, int type, int protocol);

socket函数中的domain参数用于指定通信域,domain参数取PF_UNIX时,表示创建UNIX域的套接字。使用PF_UNIX域的套接字可以实现同一机器上的不同进程间的通信。

调用bind函数实现了套接字与地址(这里是文件名)的绑定。bind函数的具体信息如下:

int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);

其参数my_addr为指向结构体sockaddr_un的指针,该结构体的定义如下:

    #define UNIX_PATH_MAX 108

    struct sockaddr_un {

    sa_family_t     sun_family;     /*PF_UNIX或AF_UNIX */

    char    sun_path[UNIX_PATH_MAX];        /* 路径名 */

    };

在该结构体中,sun_family为AF_UNIX。sun_path是套接字在文件系统中的路径名。

Unix域套接字是通过套接字API实现的简单的协议族。实际上它并不代表一个网络协议;它只能连接到同一台机器上的套接字。它提供了灵活的IPC机制。它的地址是它所在的文件系统的路径名,创建之后套接字就和路径名绑定在一起。用来表示Unix域地址的套接字文件能够使用stat()但是不能通过open()打开,而且应该使用套接字API对它进行操作。

Unix域套接字是面向连接的,每个套接字的连接都建立了一个新的通讯信道。服务器可能同时处理许多连接,但对于每个连接都有不同的文件描述符。这个属性使Unix域套接字能够比命名管道更好的适应IPC任务。

.

在一个终端运行服务器,然后在另一个终端(在相同目录下)运行客户端。当从客户端输入一行时,数据将通过套接字送到服务器。当退出客户端,服务器将等待另外一个连接。还可以通过客户端程序的重定向输入来传送文件,cat uclient.c | ./uclient 或 ./uclient < uclient.c。

服务器程序userver.c

/* userver.c - Simple Unix Domain Socket server */

/* Waits for a connection on the ./sample-socket Unix domain
   socket. Once a connection has been established, copy data
   from the socket to stdout until the other end closes the
   connection, and then wait for another connection to the 
   socket. */

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

#include "sockutil.h"          /* some utility functions */

int main(void) {
    struct sockaddr_un address;
    int sock, conn;
    size_t addrLength;

    if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        die("socket");

    /* Remove any preexisting socket (or other file) */
    unlink("./sample-socket");

    address.sun_family = AF_UNIX;       /* Unix domain socket */
    strcpy(address.sun_path, "./sample-socket");

    /* The total length of the address includes the sun_family 
       element */
    addrLength = sizeof(address.sun_family) + 
                 strlen(address.sun_path);

    if (bind(sock, (struct sockaddr *) &address, addrLength))
        die("bind");

    if (listen(sock, 5))
        die("listen");

    while ((conn = accept(sock, (struct sockaddr *) &address, 
                          &addrLength)
) >= 0) {
        printf("---- getting data\n");
        copyData(conn, 1);
        printf("---- done\n");
        close(conn);
    }

    if (conn < 0) 
        die("accept");
    
    close(sock);
    return 0;
}

客户端程序uclient.c

/* uclient.c - Simple Unix Domain Socket client */

/* Connect to the ./sample-socket Unix domain socket, copy stdin
   into the socket, and then exit. */

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "sockutil.h"          /* some utility functions */

int main(void) {
    struct sockaddr_un address;
    int sock;
    size_t addrLength;

    if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        die("socket");

    address.sun_family = AF_UNIX;    /* Unix domain socket */
    strcpy(address.sun_path, "./sample-socket");

    /* The total length of the address includes the sun_family 
       element */
    addrLength = sizeof(address.sun_family) + 
                 strlen(address.sun_path);

    if (connect(sock, (struct sockaddr *) &address, addrLength))
        die("connect");

    copyData(0, sock);

    close(sock);
    
    return 0;
}

注:如果客户端在服务器bind之前进行connect操作,connect会因为缺少套接字文件而失败。
accept和connect是两个阻塞调用。

/* sockutil.c - Utility functions used in socket example programs */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "sockutil.h"

/* issue an error message via perror() and terminate the program */
void die(char * message) {
    perror(message);
    exit(1);
}

/* Copies data from file descriptor 'from' to file descriptor 
   'to' until nothing is left to be copied. Exits if an error 
   occurs. This assumes both from and to are set for blocking 
   reads and writes. */
void copyData(int from, int to) {
    char buf[1024];
    int amount;
    
    while ((amount = read(from, buf, sizeof(buf))) > 0) {
        if (write(to, buf, amount) != amount) {
            die("write");
            return;
        }
    }
    if (amount < 0)
        die("read");
}

分享到:
评论

相关推荐

    java基于UNIX域套接字(unix domain socket)连接redis

    为了优化网络通信,有时我们会选择使用UNIX域套接字(UNIX Domain Socket,简称UDS)来代替传统的TCP/IP套接字进行进程间通信(IPC)。本篇将详细讲解如何在Java环境下,利用UNIX域套接字连接并操作Redis,以及涉及...

    UNIX域套接字 本地通信

    UNIX域套接字,也称为本地套接字或文件描述符套接字,是一种在同一台计算机上进程间通信(IPC)的有效方式。它的工作原理类似于网络套接字(TCP和UDP),但不涉及网络传输,而是通过文件系统路径进行通信。在本项目...

    经由UNIX域套接字传送文件描述符所涉及的相关知识(自己整理)

    ### 经由UNIX域套接字传送文件描述符的关键知识点 #### 1. 前言:文件描述符传输的重要性 文件描述符是操作系统分配给已打开文件的唯一标识符,通常是一个非负整数。在进程间通信(IPC)中,能够直接传输文件描述符...

    unix_socket_socket编程_Unix域套接字_udpclient_tunedaa_网络编程_源码.zip

    这个压缩包“unix_socket_socket编程_Unix域套接字_udpclient_tunedaa_网络编程_源码.zip”显然包含了一些关于Unix域套接字编程和UDP客户端(udpclient)的源代码示例,用于学习和实践网络编程技术。 Unix域套接字...

    unix_socket_socket编程_Unix域套接字_udpclient_tunedaa_网络编程_源码.rar

    标题中的“Unix_socket_socket编程”和“Unix域套接字”是关于Unix系统下的网络通信技术,特别是使用Unix域套接字(Unix Domain Sockets)进行进程间通信(IPC,Inter-Process Communication)。Unix域套接字是Unix...

    UNIX域套接字实现服务器客户端之间的通信

    UNIX域套接字实现服务器客户端之间的通信

    requests-unixsocket, 使用请求通过UNIX域套接字进行HTTP会话.zip

    requests-unixsocket, 使用请求通过UNIX域套接字进行HTTP会话 请求 UNIXSocket 使用请求通过UNIX域套接字来讨论 HTTP用法你可以通过实例化一个特殊的Session 对象来使用它:import jsonimport requests_unixsocket

    unix-path-max:获取Unix域套接字的路径的最大允许长度

    获取Unix域套接字的路径的 在Windows上不起作用。 安装 $ npm install unix-path-max 用法 const unixPathMax = require ( 'unix-path-max' ) ; ( async ( ) =&gt; { console . log ( await unixPathMax ( ) ) ; /...

    nbudstee:非阻塞Unix域套接字三通

    nbudstee:非阻塞Unix域套接字Tee 将Tees输入到零个或多个非阻塞Unix域套接字,每个套接字可以具有零个或多个连接的读取器, 和/或零个或多个现有FIFO,每个FIFO可以恰好具有一个现有读取器。 除非使用-n /-no-...

    C例子:Unix域数据报套接字通信

    Unix域套接字分为流式(SOCK_STREAM)和数据报(SOCK_DGRAM)两种类型。流式类似于TCP,提供面向连接的服务,保证数据的有序无损传输;而数据报则类似UDP,是无连接的,不保证数据顺序和可靠性,但更适合小批量、...

    linux域套接字面向连接和面向非连接的代码

    在Linux操作系统中,域套接字(也称为Unix域套接字或本地套接字)是一种进程间通信(IPC)机制,它允许同一主机上的进程之间高效地交换数据。域套接字支持两种主要的工作模式:面向连接和面向非连接,这两种模式与...

    sockdump:使用bpf转储unix域套接字流量

    转储Unix域套接字流量。 要求 密件抄送 python密件抄送绑定 例子 字符串输出 $ sudo ./sockdump.py --format string /var/run/docker.sock waiting for data 19:23:06.633 &gt;&gt;&gt; process docker [31042 -&gt; 13710] len...

    junixsocket:Java中的Unix域套接字(AF_UNIX)

    junixsocket junixsocket是一个Java / JNI库,允许使用Java的(AF_UNIX套接字)。为什么很酷junixsocket是一个小型的模块化库。 仅安装您需要的内容。 与其他实现相反, junixsocket扩展了Java Sockets API( java...

    my-uds-我的Unix域套接字绑定-Rust开发

    mio-uds一个用于将Unix域套接字与mio集成的库。 基于标准库对Unix套接字的支持,所有abstractio mio-uds除外一个用于将Unix域套接字与mio集成的库。 基于标准库对Unix套接字的支持,除了所有抽象和类型都是非阻塞的...

    jnr-unixsocket:适用于Java的UNIX域套接字(AF_UNIX)

    《深入解析jnr-unixsocket:Java中的UNIX域套接字实现》 在Java的世界里,网络通信通常依赖于基于TCP/IP的套接字。然而,对于在同一台机器上运行的进程间通信(IPC),UNIX域套接字(AF_UNIX或SOCK_UNIX)提供了...

    DomainSocket:客户端-使用Unix域套接字的服务器通信

    服务器-使用UNIX域套接字的客户端通信 功能性 DomainSocket类提供Unix域套接字的抽象。 您可以创建服务器套接字和客户端套接字进行通信。 有一个Daemon类和Sender类(服务器和客户端)作为用法示例。 例子 您可以...

    hyperlocal:用于本地unix域套接字的rustlang超绑定

    在IT领域,尤其是在网络编程和系统编程中,`Unix域套接字`(Unix Domain Sockets)是一种在相同机器上不同进程间通信的有效方式。它允许数据高效、快速地在本地进程之间传输,无需经过网络协议栈。`hyperlocal`是...

    (UINX域套接字实现小写变大写)unix_sock.tar

    linux系统中通过unix域套接字实现小写到大写的转换。对理解套接字编程有点促进作用

Global site tag (gtag.js) - Google Analytics