IPC 之 命名unix域套接字

简介

        unix域套接字用于在同一台机器上运行的进程之间的通信。虽然因特网域套接字可用于同一目的,但是unix域套接字效率更高。unix域套接字仅仅复制数据;它们并不执行协议处理,不需要添加或删除网络报头,无需计算校验和,不要产生顺序号,无需发送确认报文。

        unix域套接字的地址由sockaddr_un结构表示。sockaddr_un结构按下列形式定义在头文件<sys/un.h>中

        structsockaddr_un{

               sa_family_t sun_family;    /*AF_UNIX */

               char       sun_path[108];   /* pathname */

        };

但是在FreeBSD等其他操作系统中,sockaddr_un结构定义如下:

        structsockaddr_un{

               unsignedchar sun_len;     /* length including null */

               sa_family_t   sun_family; /*AF_UNIX */

               char          sun_path[104];   /* pathname */

        };

        sockaddr_un结构的sun_path成员包含一路径名。当我们将一个地址绑定至unix域套接字时,系统用该路径名创建一类型为S_IFSOCK的文件。该文件仅用于向客户进程告知套接字名字。该文件不能打开,也不能由应用程序用于通信。

        如果当我们试图绑定地址时,该文件已存在,那么bind请求会失败。关闭套接字时,并不自动删除该文件,所以必须确保在应用程序终止前,对该文件执行解除链接操作。

示例程序


服务端

#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
#include<unistd.h>
#include<errno.h>
#include<sys/socket.h>
#include<sys/un.h>
 
#definePATH "/tmp/ipc_sock"
#defineQUEUE_LEN 10
 
int
main(int argc, char *argv[])
{
    int                serfd, clifd, len, ret;
    char               rcv_buf[1024];
    pid_t               pid;
    struct sockaddr_un server_addr, client_addr;
 
    if((serfd = socket(AF_UNIX,SOCK_STREAM, 0)) < 0){
        perror("Createserver socket error");
        exit(EXIT_FAILURE);
    }
 
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family= AF_UNIX;
    strncpy(server_addr.sun_path, PATH, sizeof(PATH));
    len =offsetof(struct sockaddr_un, sun_path) + strlen(PATH);
 
    unlink(server_addr.sun_path);
 
    if(bind(serfd, (structsockaddr *)&server_addr, len) < 0){
        perror("Bindserver socker error");
        close(serfd);
        unlink(PATH);
        exit(EXIT_FAILURE);
    }
if(listen(serfd,QUEUE_LEN) < 0){
        perror("Listenserver socker error");
        close(serfd);
        unlink(PATH);
        exit(EXIT_FAILURE);
    }
 
    len = sizeof(client_addr);
 
    for(;;){
        if((clifd = accept(serfd,
(structsockaddr *)&client_addr, &len)) < 0){
            perror("Cannot accept client connect request");
            continue;
        }
 
        pid = fork();
 
        if(pid < 0){
            perror("forkerror!");
        }else if(pid == 0){
            ret = read(clifd, rcv_buf, sizeof(rcv_buf));
            if(ret <= 0){
                perror("readerror");
            }else{
                printf("receivedata : %s\n", rcv_buf);
            }
        }else{
        }
    }
 
    close(serfd);
close(clifd);
unlink(PATH);
 
    return(0);
}

客户端

#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/un.h>
 
#definePATH "/tmp/ipc_sock"
 
int
main(int argc, char **argv)
{
    int     fd, ret, len;
    char    *send_buf= "hello,world!";
    struct sockaddr_un addr;
 
    if((fd = socket(PF_UNIX,SOCK_STREAM, 0)) < 0){
        perror("Createsocket error");
        exit(EXIT_FAILURE);
    }
 
    memset(&addr, 0, sizeof(addr));
    addr.sun_family= AF_UNIX;
    strncpy(addr.sun_path, PATH, strlen(PATH));
    len =offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
 
    if((ret = connect(fd, (structsockaddr *)&addr, len)) < 0){
        perror("Cannot connect server");
        close(fd);
        exit(EXIT_FAILURE);
    }
 
    ret = write(fd,send_buf, strlen(send_buf));
    if(ret < 0){
        printf("writeerror!");
    }
 
    close(fd);
 
    return(0);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值