unix域协议

1. 概述

Unix域协议可以看做是IPC中的一种。它提供两类套接字,字节流套接字(类似TCP),数据报套接字(类似UDP。应用较少)。
使用它有以下三大优势:

  1. 比TCP套接字快出一倍多。
  2. 可以在不同进程之间传递文件描述符。
  3. 把用户凭据(用户ID、组ID)提供给服务器,从而进行安全检查。
    Unix域中用于标识服务器和客户机的协议地址是普通文件的路径名。
2. 一个Unix域字节流C/S程序
2.1 创建Socket
 int socket(int domain, int type, int protocol);
 domain这里填AF_UNIX或AF_LOCAL用来标识是本地通信
 type为SOCK_STREAM,字节流
2.2 删除路径并绑定

如果不unlink这个路径名,bind会失败。并这个路径一般是绝对路径,相对路径对C/S两端有同路径的限制。
这个文件的默认访问权限应该是0777,可按照当前的umask进行修正。比如umask是0022,那么创建文件的权限就是,0777-0022 = 0755。

套接字地址如下,

struct sockaddr_un {
  sa_family_t sun_family; /*AF_LOCAL或AF_UNIX */
  char sun_path[UNIX_PATH_MAX]; /* 路径名 UNIX_PATH_MAX是104*/
};
2.3 connect

客户端connect时必须和server端bind的文件路径是一致的。不同于TCP,这里connect调用发现监听套接字的队列满了的时候,立马就会返回一个ECONNECTREFUSED错误,TCP则会数次发送SYN进行重试。

3. 代码实例

server.c

#define PATH "/tmp/socket_file"

int main() {
    // 1. 创建socket
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket error");
        return -2;
    }

    // 2. 删除连接,否则不能绑定
    unlink(PATH);

    struct sockaddr_un serv;
    bzero(&serv, sizeof(serv));
    serv.sun_family = AF_UNIX;
    strncpy(serv.sun_path, PATH, sizeof(serv.sun_path) - 1);

    // 3. 绑定
    int ret = bind(sockfd, (struct sockaddr*)&serv, sizeof(serv));
    if (ret < 0) {
        perror("bind error");
        return -3;
    }

    // 4. 监听
    listen(sockfd, 5);

    // 5. accept
    int connfd = accept(sockfd, NULL, NULL);
    if (connfd < 0) {
        perror("accept error");
        return -4;
    }

    char buff[1024];
    while (1) {
        ret = recv(connfd, buff, sizeof(buff), 0);
        if (ret < 0) {
            perror("recv error");
            return -5;
        }

        write(1, buff, ret);
        if (strncmp(buff, "quit", 4) == 0) {
            break;
        }
    }

    close(connfd);
    close(sockfd);

    return 0;
}

client.cpp

#define PATH "/tmp/socket_file"

int main(int argc, char *argv[]) {
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket error");
        return -1;
    }

    struct sockaddr_un serv;
    bzero(&serv, sizeof(serv));
    serv.sun_family = AF_UNIX;
    strcpy(serv.sun_path, PATH);

    int ret = connect(sockfd, (struct sockaddr *)&serv, sizeof(serv));
    if (ret < 0) {
        perror("connect error");
        return -2;
    }

    char buff[1024];
    while (1) {
        ret = read(0, buff, sizeof(buff));
        if (ret < 0) {
            perror("read error");
        }
        ret = send(sockfd, buff, ret, 0);
        if (ret < 0) {
            perror("send error");
            return -4;
        }
        if (strncmp(buff, "quit", 4) == 0) {
            break;
        }
    }
    close(sockfd);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值