Skip to content

Instantly share code, notes, and snippets.

@leiless
Last active September 18, 2023 08:12
Show Gist options
  • Save leiless/12f9493091aadb0a7873a864c7cb4732 to your computer and use it in GitHub Desktop.
Save leiless/12f9493091aadb0a7873a864c7cb4732 to your computer and use it in GitHub Desktop.
Windows AF_UNIX UNIX domain socket example
// Taken from with modifications
// https://devblogs.microsoft.com/commandline/windowswsl-interop-with-af_unix/#windows-server-code
#undef UNICODE
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <afunix.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define SERVER_SOCKET "server.sock"
int __cdecl main(void)
{
SOCKET server_socket_fd = INVALID_SOCKET;
SOCKET client_socket_fd = INVALID_SOCKET;
int rc = 0;
char send_buf[] = "AF_UNIX from Windows!";
SOCKADDR_UN socket_addr = { 0 };
WSADATA wsa_data = { 0 };
// Initialize Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (rc != 0) {
printf("WSAStartup() error: %d\n", rc);
goto out_exit;
}
// Create a AF_UNIX stream server socket
server_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_socket_fd == INVALID_SOCKET) {
printf("socket() error: %d\n", WSAGetLastError());
goto out_exit;
}
socket_addr.sun_family = AF_UNIX;
strncpy_s(socket_addr.sun_path, sizeof socket_addr.sun_path, SERVER_SOCKET, (sizeof SERVER_SOCKET) - 1);
// Remove previously created server socket file
rc = remove(SERVER_SOCKET);
if (rc != 0) {
rc = WSAGetLastError();
if (rc != ENOENT) {
printf("remove() error: %d\n", rc);
goto out_exit;
}
}
// Bind the socket to the path
rc = bind(server_socket_fd, (struct sockaddr *) &socket_addr, sizeof(socket_addr));
if (rc == SOCKET_ERROR) {
printf("bind() error: %d\n", WSAGetLastError());
goto out_exit;
}
// Listen to start accepting connections
rc = listen(server_socket_fd, SOMAXCONN);
if (rc == SOCKET_ERROR) {
printf("listen() error: %d\n", WSAGetLastError());
goto out_exit;
}
printf("Accepting connections on: '%s'\n", SERVER_SOCKET);
// Accept a connection
client_socket_fd = accept(server_socket_fd, NULL, NULL);
if (client_socket_fd == INVALID_SOCKET) {
printf("accept() error: %d\n", WSAGetLastError());
goto out_exit;
}
printf("Accepted a connection.\n" );
// Send some data
rc = send(client_socket_fd, send_buf, (int) strlen(send_buf), 0);
if (rc == SOCKET_ERROR) {
printf("send() error: %d\n", WSAGetLastError());
goto out_exit;
}
printf("Relayed %zu bytes: '%s'\n", strlen(send_buf), send_buf);
// Shutdown the connection
printf("Shutting down\n");
rc = shutdown(client_socket_fd, 0);
if (rc == SOCKET_ERROR) {
printf("shutdown() error: %d\n", WSAGetLastError());
goto out_exit;
}
out_exit:
// Cleanup
if (server_socket_fd != INVALID_SOCKET) {
closesocket(server_socket_fd);
}
if (client_socket_fd != INVALID_SOCKET) {
closesocket(client_socket_fd);
}
// Analogous to `unlink`
DeleteFileA(SERVER_SOCKET);
WSACleanup();
return 0;
}
@leiless
Copy link
Author

leiless commented Sep 18, 2023

client.c

#undef UNICODE

#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <afunix.h>
#include <stdlib.h>
#include <stdio.h>

#define SERVER_SOCKET "server.sock"

int __cdecl main(void)
{
    SOCKET socket_fd = INVALID_SOCKET;
    int rc = 0;
    char recv_buf[128];
    SOCKADDR_UN socket_addr = { 0 };
    WSADATA wsa_data = { 0 };

    // Initialize Winsock
    rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
    if (rc != 0) {
        printf("WSAStartup() error: %d\n", rc);
        goto out_exit;
    }

    // Create a AF_UNIX stream server socket
    socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (socket_fd == INVALID_SOCKET) {
        printf("socket() error: %d\n", WSAGetLastError());
        goto out_exit;
    }

    socket_addr.sun_family = AF_UNIX;
    strncpy_s(socket_addr.sun_path, sizeof socket_addr.sun_path, SERVER_SOCKET, (sizeof SERVER_SOCKET) - 1);

    // Connect to the server socket
    rc = connect(socket_fd, (struct sockaddr *) &socket_addr, sizeof(socket_addr));
    if (rc == SOCKET_ERROR) {
        printf("connect() error: %d\n", WSAGetLastError());
        goto out_exit;
    }

    // Receive data from server
    rc = recv(socket_fd, recv_buf, sizeof(recv_buf), 0);
    if (rc < 0) {
        printf("recv() error: %d\n", WSAGetLastError());
        goto out_exit;
    }

    // Print out the received data
    printf("Received data len: %d\n", rc);
    printf("%.*s\n", rc, recv_buf);

out_exit:
    // Cleanup

    if (socket_fd != INVALID_SOCKET) {
        closesocket(socket_fd);
    }

    WSACleanup();

    return 0;
}

@leiless
Copy link
Author

leiless commented Sep 18, 2023

Compile and run

https://github.com/niXman/mingw-builds-binaries
https://github.com/mstorsjo/llvm-mingw

https://blogs.msdn.microsoft.com/commandline/2017/12/19/af_unix-comes-to-windows/
https://devblogs.microsoft.com/commandline/windowswsl-interop-with-af_unix/

gcc -Wall server.c -o server -lws2_32
gcc -Wall client.c -o client -lws2_32

$ ./server.exe
Accepting connections on: 'server.sock'
Accepted a connection.
Relayed 21 bytes: 'AF_UNIX from Windows!'
Shutting down

$ ./client.exe
Received data len: 21
AF_UNIX from Windows!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment