Search code examples
clinuxwindowssocketsenvironment

Which equivalent headers, functions, and data types do I need to replace while doing C socket programming on windows?


I have started C socket programming recently. After some days of learning, I wrote this program, which listens for connection on a specific IP and port:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>


int main()
{
    printf ("The program has started\n");
    
    int sock, client_socket;
    char buffer[1024];
    char response[1024];
    struct sockaddr_in server_address, client_address;
    int i = 0;
    int optval = 1;
    socklen_t client_length;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
    {
        printf("Error setting TCP socket options!\n");
        return 1;
    }
    else {
        printf ("TCP socket set successfully!\n");
    }

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr("10.0.2.15");
    server_address.sin_port = htons(5005);

    int stat_check = bind (sock, (struct sockaddr*) &server_address, sizeof (server_address));
    if (stat_check != 0)
    {
        printf ("Couldn't bind\n");
    }
    else {
        printf ("binded successfully\n");
    }
    
    stat_check = listen(sock, 5);
    if (!(stat_check == 0))
    {
        printf ("Failed to listen!\n");
    }
    else {
        printf ("Listening...\n");
    }
    printf ("now the program will attempt to accept the connectionHSHA\n");
    client_length = sizeof(client_address);
    client_socket = accept (sock, (struct sockaddr*) &client_address, &client_length);
    printf ("Socket Accepted or something happened\n");
    
    if (client_socket == -1)
    {
        printf ("Couldn't accept connection!\n");
    }
    else 
    {
        printf ("Connection Accepted!\n");
    }

    while (1)
    {
        jump:
        bzero(&buffer, sizeof(buffer));
        bzero(&response, sizeof(response));
        printf("* Shell#%s~$: ", inet_ntoa(client_address.sin_addr));
        fgets(buffer, sizeof(buffer), stdin);
        strtok(buffer, "\n");
        write(client_socket, buffer, sizeof(buffer));

        if (strncmp("q", buffer, 1) == 0)
        {
            break;
        }
        else
        {
            recv(client_socket, response, sizeof(response), MSG_WAITALL);
            printf("%s", response);
        }
    }
}

This program compiles 100% fine in my Linux system, but I need it to run on windows. When I compile the same program on my windows with the MinGW compiler, it runs into many missing-header errors. However, there are some libraries for socket programming in windows, such as winsock.h. But still when I replace winsock.h with <sys/socket> and remove other Linux libraries(arpa/inet.h, etc), there are some other errors like socklen_t undefined. I also receive some warnings.

Altogether, I am not clear which equivalent libraries, functions, and data types I need to replace if I want to run this code on windows. Or can I run it on windows in any other way? Any suggestions will be greatly appreciated.

Thanks!


Solution

  • Here is a simple but complete sample of a server servicing TCP with sockets under Windows.

    It accept several simultaneous clients and serve them with a thread. The server accept command lines from each client and echo them at server side (Easy to echo back to the client with a simple send). If the command is "exit" the server close the connection.

    There are room for many enhancements of course. You've got the idea...

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <WinSock2.h>
    
    #define portNo 2100
    #define MAX_CLIENTS 10
    
    struct clientData {
        int    busy;
        int    inSocket;
        HANDLE hThread;
        DWORD  threadId;
    };
    
    struct clientData cliArray[MAX_CLIENTS];
    int cliCount;
    
    DWORD WINAPI ClientThreadFunction(LPVOID lpParam)
    {
        struct clientData* cliData = (struct clientData*)lpParam;
        printf("[%d] Client start. Socket=%d\n", cliData->inSocket, cliData->inSocket);
    
        char buf[1024];
        int rcvLen;
        int rcvCount = 0;
        char ch;
        while (1) {
            rcvLen = recv(cliData->inSocket, &ch, 1, 0);
            if (rcvLen <= 0)
                break;
            if (ch == '\r')
                continue;      // Ignore return character (followed by '\n')
            if (ch != '\n') {
                putchar(ch);
                buf[rcvCount++] = ch;
                buf[rcvCount] = 0; // nul terminate string
            }
            else {
                printf("\n[%d] Line=\"%s\"\n", cliData->inSocket, buf);
                if (_stricmp(buf, "exit") == 0)
                    break;
                rcvCount = 0;
                buf[0] = 0;
            }
        }
    
        closesocket(cliData->inSocket);
    
        printf("[%d] Client terminated.\n", cliData->inSocket);
        cliData->busy = 0;
        return 1;
    }
    
    int main(int argc, char *argv[])
    {
        int iResult;
        WSADATA wsaData;
    
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed: %d\n", iResult);
            return 1;
        }
    
        int srvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (srvSocket < 0) {
            fprintf(stderr, "Open socket failed with error %d\n", WSAGetLastError());
            return 1;
        }
    
        struct sockaddr_in sockAddr;
    
        memset(&sockAddr, 0, sizeof(sockAddr));
        sockAddr.sin_family = AF_INET;
        sockAddr.sin_port = htons(portNo);
        sockAddr.sin_addr.s_addr = INADDR_ANY;
    
        if (bind(srvSocket, (struct sockaddr*)&sockAddr, sizeof(sockAddr))) {
            fprintf(stderr, "bind socket failed with error %d\n", WSAGetLastError());
            closesocket(srvSocket);
            WSACleanup();
            return 1;
        }
    
        if (listen(srvSocket, 5)) {
            fprintf(stderr, "listen socket failed with error %d\n", WSAGetLastError());
            closesocket(srvSocket);
            WSACleanup();
            return 1;
        }
        
        while (1) {
            int inSocket = accept(srvSocket, NULL, NULL);
            if (inSocket == INVALID_SOCKET) {
                fprintf(stderr, "accept socket failed with error %d\n", WSAGetLastError());
                closesocket(srvSocket);
                WSACleanup();
                return 1;
            }
            struct clientData* cliData = cliArray;
            int i = 0;
            while ((i < MAX_CLIENTS) && cliArray[i].busy)
                i++;
            if (i >= MAX_CLIENTS) {
                // To many clients, disconnect
                closesocket(inSocket);
                printf("Too many active clients (max=%d), discarding this one\n", MAX_CLIENTS);
                continue;
            }
            cliData = &cliArray[i];
            cliData->busy = 1;
            cliData->inSocket = inSocket;
            cliData->hThread = CreateThread(
                NULL,                            // default security attributes
                0,                               // use default stack size  
                ClientThreadFunction,            // thread function name
                cliData,                         // argument to thread function 
                0,                               // use default creation flags 
                &cliData->threadId);             // returns the thread identifier 
        }
    
        closesocket(srvSocket);
        WSACleanup();
        printf("Done.\n");
        return 0;
    }