Use Linux C Socket API in Windows

Introduction

Whenever we want to do socket programming in c, we got two choices primarily; one is to use socket API in Linux and another one is Winsock which is for Windows, but sometimes we have some constraints due to which we want to use linux socket api in windows. We will see how to do the same.

How do we do it?

We will install wsl in windows to use linux packages in windows, further to reduce tedious tasks of starting wsl, creating folders, compiling files, etc. We will use vscode to make our task easy.

1. Installing WSL in Windows

  • For detailed instructions, refer here.
  • RightClick on the windows start menu icon and click on Windows PowerShell(Admin).
  • In the opened window, write following command, which will install wsl with ubuntu distro. You can change it according to your preference:
    wsl --install -d Ubuntu
    
  • After installation, it will ask you to set up a username and password.
  • After setting up username and password, you will see that wsl has started, now write the following command:
    sudo apt update && sudo apt upgrade
    
  • After that, type "exit" to get out from wsl and then close the PowerShell window.

2. Setting Up VSCode

  • You can use any development ide or text editor for socket programming but vscode provides a straightforward interface to manage wsl using extensions so we will use vscode.
  • Open vscode for particular folder.
  • Then open extension tab from left side and search for "ms-vscode-remote.remote-wsl" and install it. vscode_wsl_ext.png
  • After installing it, on the bottom left side, you will see remote wsl button, click on it, which will open the following box from that select "Reopen folder in WSL" and hit enter. Screenshot (289).png

3. Compiling and Running Socket Programming Code

  • From the menu bar, open the Terminal tab and click on New Terminal.
  • For the first time, we need to install gcc and gdb using the following command:

    sudo apt install gcc && sudo apt install gdb
    
  • As you can see, the following server.c and client.c includes sys/socket.h files which are not supported on windows.

  • server file
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>

#define PORT 8080

int main(int argc, char *argv[]) {
    int server_fd, new_socket, valread;
    struct sockaddr_in address;
    int opt = 1;
    int addr_len = sizeof(address);
    char buffer[1024], response[1024];
    char *msgToSendBack = response;

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket Creation Failed");
        exit(EXIT_FAILURE);
    }

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,&opt, sizeof(opt))) {
        perror("Set Can't be attached");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
        perror("Can't Bind");
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 3) < 0) {
        perror("Can't Listen");
        exit(EXIT_FAILURE);
    }

    if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addr_len)) < 0) {
        perror("Connection can't be accpeted");
        exit(EXIT_FAILURE);
    }
    while(1) {
        valread = read(new_socket, buffer, 1024);
        buffer[valread] = '\0';
        printf("Incoming Message: %s\n", buffer);

        if (strncasecmp("How are you?",buffer, strlen("How are you?")) == 0) {
            send(new_socket, "I am fine", strlen("I am fine"), 0);
        }
        else {
            strcpy(msgToSendBack, buffer);
            strcat(msgToSendBack, " Message Received");
            send(new_socket, msgToSendBack, strlen(msgToSendBack), 0);
        }

        printf("Response Message Sent\n");
        fflush(stdout);

        memset(buffer, 0, 1024);
        memset(response, 0, 1024);
    }

    return 0;
}
  • client.c
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

#define PORT 8080

int main(int argc, char *argv[]) {
    int sock = 0, valread;
    struct sockaddr_in serv_addr;
    char *exit_msg = "exit", *msg;
    char buffer[1024] = {0};

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("\n Socket Connection Error");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        printf("\n Invalid address");
        return -1;
    }

    if (connect(sock, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
        printf("\n Connection Failed\n");
        return -1;
    }

    while (1) {
        printf("Enter Message for server:");
        scanf("%[^\n]%*c", msg);

        if(!strcmp(msg, exit_msg)) {
            close(sock);
            return 0;
        }

        send(sock, msg, strlen(msg), 0);
        valread = read(sock, buffer, 1024);
        printf("From Server: %s\n", buffer);
    }

    return 0;
}
  • Now, using a terminal window that we opened earlier, write the following commands to compile the files

    gcc server.c -o server
    gcc client.c -o client
    
  • Now, run the server file in the same terminal window using the following command

    ./server
    
  • Open another terminal window and run the client file.

    ./client
    
  • This way you can run linux socket api in windows.

Happy Coding :)