Windows Named Pipe Support in Linux

Windows Named Pipe Support in Linux

Windows and Linux named pipes are different animals. If an interop solution exists you are going to be one of a very small population of users.

You might be better off writing a proxy on the Windows side to map between Named Pipe and socket, and connecting this to a socket on the Linux end. This provides you a useful networked interface on the Linux side going forward, and removes what might be a world of Named Pipes interop hurt from the picture.

If I was doing this I would try to produce a simple passthrough proxy in C# (managed code) as a proof of concept. Can always convert to native code (Win32/C++) if throughput does not measure up. There is some sample C# code here that might be a useful reference.

Here is background on the nuances of Windows vs Linux named pipes.

Windows NAmed Pipes alternative in Linux

Unix sockets. Essentially,

  1. Call socket(PF_UNIX, SOCK_STREAM, 0). This returns a file descriptor or -1 on error.
  2. Use something like struct sockaddr_un addr; bzero(addr); addr.sun_len = sizeof(addr); addr.sun_family = PF_UNIX; strncpy(addr.sun_path, "/path/to/file", sizeof(addr.sun_path)-1); to create the socket address.
  3. Call bind(fd, &addr, sizeof(addr)).
  4. call listen(fd,backlog) to listen for connections. backlog is the number of un-accept()ed connections that can exist.
  5. Use accept() to accept connections from clients. This returns a new FD or -1 on error.
  6. Have clients create a similar socket and connect() to the address (I don't think they have to bind).
  7. Remove the file /path/to/file when done (or just leave it there if you're going to reuse it later).

I'm not sure if SOCK_DGRAM is supported for Unix sockets (if so, it's probably UDP-like).

See the man pages for socket(2), bind(2), listen(2), accept(2), connect(2), unix(4), setsockopt(2).

For "overlapped I/O", see select(2). You can additionally enable non-blocking IO with fcntl(fd,F_SETFL,(int)(fcntl(fd,F_GETFL)|O_NONBLOCK)) (see fcntl(2)), this means read() and write() never block (which means write() can return short, so you need to look at the return value).

I'm not quite sure how Windows named pipes represent multiple connections from multiple clients, but in UNIX, you get one file descriptor per connection (plus one for the "listening" socket).

What are the differences between pipes in Windows and Linux?

One difference that I know of, is that named pipes under Linux are actual entries in the filesystem (you'll see it in a directory listing, they have a special type), whereas on Windows they are stored in some magical repository somewhere (they are all accessed via the path "\\.\pipe\".

Secondly, in Linux you can just write/read from pipes as if they were any other file, using standard file IO methods. Whereas on windows, you have to use the special 'Pipe' functions which are part of the Win32 API.

I like linux's method better, because it lets me use pipes with any app I want. Eg:

mkfifo pipe.wav
decodeMP3 song.mp3 --out pipe.wav &
encodeAVI video.mpeg pipe.wav --out video.avi

This lets me pipe the output of the MP3 decoder directly into the video decoder, instead of having to first decode the entire MP3 into a WAV file on disk. It's handy if you have a dual-core CPU, because then you are running both operations at once, for a nice speedup.

WINE and Windows named pipes

Named pipes are hosted by the WINE server process. Requests are sent to this process by the WINE clients. For example, CreateNamedPipe uses a request like:

    SERVER_START_REQ( open_file_object )
{
req->access = access;
req->attributes = attr->Attributes;
req->rootdir = wine_server_obj_handle( attr->RootDirectory );
req->sharing = sharing;
req->options = options;
wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
io->u.Status = wine_server_call( req );
*handle = wine_server_ptr_handle( reply->handle );
}

The server manages connecting the named pipe. Once a client and server have connected, the WINE server gets out of the way by sending an fd to the client. I think this fd is just an anonymous pipe created by the WINE server, one end being sent to the pipe server and one end to the pipe client.

Communication between Windows Host and Linux Docker Container

Linux do have named pipes, though the exact semantic of different operations vary, but the problem you'll have is that named pipe cannot be used to communicate between different systems. Named pipe is an inter-process communication for process running on the same machine. Note that Windows Host and Linux Guest are considered two separate systems here even when they live in the same physical machines.

TCP is the most general purpose form of sockets and is the standard way to connect between two OSes. If you don't know why you want to use the other protocols, TCP is usually a good bet that it'll be able to connect almost everything.

Now the only problem is what application level protocol you want to use, and whether you want to add any security layer (i.e. TLS) to encrypt and authenticate the connection between the machines. If you have a simple service that only needs to transmit simple strings, then you probably can just use TCP/TLS socket directly, but if you want to benefit from standardized phraseology, techniques, and libraries and frameworks for various things like communicating request and responses statuses, authentication, optimistic locking, caching, proxying, session management, arbitrary length stream encoding, etc, then building your communication on top of HTTP/HTTPS is a sensible thing to do. You'll find that a lot of services nowadays are built as a web service as it makes things a lot simpler when you need to scale and make use of those features.

How to open a Windows named pipe from Java?

Use Named Pipes to Communicate Between Java and .Net Processes

Relevant part in the link

try {
// Connect to the pipe
RandomAccessFile pipe = new RandomAccessFile("\\\\.\\pipe\\testpipe", "rw");
String echoText = "Hello word\n";
// write to pipe
pipe.write ( echoText.getBytes() );
// read response
String echoResponse = pipe.readLine();
System.out.println("Response: " + echoResponse );
pipe.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


Related Topics



Leave a reply



Submit