c - `bind()` unix 域套接字客户端进程有什么用途吗?

标签 c sockets unix system

当使用 AF_UNIX(unix 域套接字)时,是否有任何应用程序可以在从不调用 listen() 的进程中调用 bind() >?

在我的系统编程讲座和实验室中,我们被指示在 unix 域套接字客户端进程上调用 bind()。在 client-only unix domain socket 进程上调用 bind 是否有任何已记录、未记录或实际的应用程序?根据我的理解,bind() 创建了特殊的套接字文件,这是服务器进程将承担的责任。这是正确的吗?

这是一个基于类里面讨论的概念的示例代码:

服务器.c

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

int main() {
    int s0, s1;
    struct sockaddr sa0 = {AF_UNIX, "a"};

    s0 = socket(AF_UNIX, SOCK_STREAM, 0);

    bind(s0, &sa0, sizeof(sa0) + sizeof("a"));
    listen(s0, 1);
    for (;;) {
        s1 = accept(s0, NULL, NULL);
        puts("connected!");
        for (;;) {
            char text[1];
            ssize_t n = read(s1, &text, sizeof(text));
            if (n < 1) {
                break;
            }
            putchar(text[0]);
        }
        close(s1);
    }
    close(s0);
    unlink("a");
    return 0;
}

客户端.c

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

int main() {
    int s0;
    struct sockaddr sa0 = {AF_UNIX, "b"};
    struct sockaddr sa1 = {AF_UNIX, "a"};
    socklen_t sa1_len;

    s0 = socket(AF_UNIX, SOCK_STREAM, 0);
    bind(s0, &sa0, sizeof(sa0) + sizeof("b")); // What does this do??
    connect(s0, &sa1, sizeof(sa1) + sizeof("b"));
    for (;;) {
        int c = fgetc(stdin);
        if (c == EOF) {
            break;
        }
        write(s0, &c, sizeof(c));
    }
    close(s0);
    unlink("b");
    return 0;
}

最佳答案

仅当您需要接收与 SOCK_STREAM 类型套接字的连接时才需要调用 bind(),但 bind() 行为取决于 SOCKET 的域。有一个 manual专用于此的页面。

有用的信息:

Address format

A UNIX domain socket address is represented in the following structure:

#define UNIX_PATH_MAX    108

struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[UNIX_PATH_MAX];  /* pathname */
};

Three types of address are distinguished in this structure:

  • pathname: a UNIX domain socket can be bound to a null-terminated file system pathname using bind(2). When the address of the socket is returned by getsockname(2), getpeername(2), and accept(2), its length is offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1, and sun_path contains the null-terminated pathname.

  • unnamed: A stream socket that has not been bound to a pathname using bind(2) has no name. Likewise, the two sockets created by socketpair(2) are unnamed. When the address of an unnamed socket is returned by getsockname(2), getpeername(2), and accept(2), its length is sizeof(sa_family_t), and sun_path should not be inspected.

  • abstract: an abstract socket address is distinguished by the fact that sun_path[0] is a null byte ('\0'). The socket's address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure. (Null bytes in the name have no special significance.) The name has no connection with file system pathnames. When the address of an abstract socket is returned by getsockname(2), getpeername(2), and accept(2), the returned addrlen is greater than sizeof(sa_family_t) (i.e., greater than 2), and the name of the socket is contained in the first (addrlen

  • sizeof(sa_family_t)) bytes of sun_path. The abstract socket namespace is a nonportable Linux extension.

Binding to a socket with a filename creates a socket in the file system that must be deleted by the caller when it is no longer needed (using unlink(2)). The usual UNIX close-behind semantics apply; the socket can be unlinked at any time and will be finally removed from the file system when the last reference to it is closed.


所以:

  • bind() 在客户端中不是必需的。
  • bind() 在您的上下文中为您的套接字命名 "a""b"
  • bind(s0, &sa0, sizeof(sa0) + sizeof("b")); 和您代码中的类似行是未定义的行为;它给 bind() 一个错误的大小,超过了 &sa0 的界限。正确的代码是 bind(s0, &sa0, sizeof sa0);
  • bind() 在此上下文中(Linux、AF_UNIX)确实创建了一个特殊的套接字文件;如果你想删除它,你必须调用 unlink()remove()

关于c - `bind()` unix 域套接字客户端进程有什么用途吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47703401/

相关文章:

c - 在 Xcode 中,如何禁用缩进宏处理?

c - 两个数组的总和

java - 数据不会写入 printwriter

php - 为什么需要MINUTE才能从服务器获得响应?

linux - 使用top命令监控Linux服务器的系统性能

c - SIGUSR1 和 SIGUSR2 的区别

c++ - GDB - 访问复数的实部和虚部

循环内的 CUDA 复制和内核调用

java - 为什么套接字不使用 ip 而不是 localhost 连接?

linux - awk 的多输入文件