Home > Blockchain >  Calling open() on a Unix domain socket failed with error "No such device or address"
Calling open() on a Unix domain socket failed with error "No such device or address"

Time:09-16

I'm trying to communicate between NodeJS and C program using named pipes in linux. My server program has written in NodeJS:

'use strict';

const net = require('net');
const pipename = '/tmp/pipe1';
const fs = require('fs');

let server = net.createServer(function(socket){
        console.log('A new connection');
        socket.on('data',function(data){
                console.log(data.toString());
        });
        socket.on('end',function(){
                console.log('Closed connection');
        });
});

server.on('error',console.log);

fs.unlink(pipename,function(){
        server.listen(pipename);
})

//Test unix-socket server:
setInterval(function(){
        var stream = net.connect(pipename);
        stream.on('error',console.log);
        stream.write('hello');
        stream.end();
},2000);

However, when I want to open the pipe inside C even after the NodeJS server has already started, I get error:

const char* pipename = "/tmp/pipe1";
int hPipe = open(pipename, O_WRONLY); //Error: No such device or address

When I try to do echo 'Hello World!' > /tmp/pipe1, I get bash: /tmp/pipe1: No such device or address. But ls -l /tmp yields:

srwxr-xr-x 1 root root    0 Sep 16 03:20 pipe1

How can I solve this issue?

CodePudding user response:

The /tmp/pipe1 is not a pipe file. It's a socket file. That's what the leading s means in srwxr-xr-x.

And Bash's redirection like > does not support socket files. You need to use socket API to open the file.


With strace (e.g. strace bash -c 'echo > /tmp/sockfile') we can see:

...
openat(AT_FDCWD, "/tmp/sockfile", ...) = -1 ENXIO (No such device or address)
...

So the error code is ENXIO whose corresponding error message is No such device or address. Bash is just calling standard C API (like strerror) to print the error.


Exampe code for client side:

int
sock_connect(char * sockpath)
{
    int sock_fd;
    struct sockaddr_un srv_addr = { 0 };

    sock_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (sock_fd < 0) {
        return -1;
    }

    srv_addr.sun_family = AF_LOCAL;
    snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s", sockpath);
    if (connect(sock_fd, (struct sockaddr *) & srv_addr, sizeof(srv_addr)) < 0) {
        return -1;
    }

    return sock_fd;
}
  • Related