Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

Is is possible to implement a client / server program using the online compiler?

+5 votes
asked May 15, 2022 by Shawn Armstrong (330 points)

I thought about trying to get this client/server implementation to work using the online compilers. Using this program, I noticed the IP address changes every time you run. Which leads me to believe it's not really possible unless somebody can think of a witty work around?

1 Answer

+1 vote
answered May 21, 2022 by xDELLx (10,500 points)
selected Jun 12, 2022 by Shawn Armstrong
 
Best answer

https://onlinegdb.com/VjEji9cJH

The trick is to use loopback ip for both client & server.

when creating server socket, specify the loopback ip for binding(Line #131).

Also since i cant run client & server on seperate instances of onlineGDB, i created a client thread to run parallel to server(main) thread.

the placement of running of child thread is crucial as we have start cleint thread after server socket is bound & not yet listening.

As listen(& few other api,by default) socket calls are blocking & pause execution, i think its the best place to spawn a child thread.


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

#define MAX 80
#define PORT 9090
#define SA struct sockaddr
void func(int connfd)
{
    char buff[MAX];
    int n=0;
    // infinite loop for chat
    for (;;)
    {
        bzero(buff, MAX);

        // read the message from client and copy it in buffer
        read(connfd, buff, sizeof(buff));
        // print buffer which contains the client contents
        printf("I am Server || Msg from client ==>> %s\n", buff);
        bzero(buff, MAX);
        // copy server message in the buffer
        //while ((buff[n++] = getchar()) != '\n')
            ;
        sprintf(buff,"** got !! msg %d from Server **\n",n);
        // and send that buffer to client
        write(connfd, buff, sizeof(buff));

        // if msg contains "Exit" then server exit and chat ended.
        if (strncmp("exit", buff, 4) == 0) {
            printf("Server Exit...\n");
//            break;
        }
        sleep(2);
        n++;
    }
}

void client_func(int sockfd)
{
    char buff[MAX];
    int n=0;
    for (;;)
    {
        bzero(buff, sizeof(buff));
        //printf("Enter the string : ");
    n++;
    sprintf(buff,"Msg %d to server !!\n",n);
        write(sockfd, buff, sizeof(buff));
        bzero(buff, sizeof(buff));
        read(sockfd, buff, sizeof(buff));
        printf("I am Client || Msg From Server : %s\n", buff);

        if ((strncmp(buff, "exit", 4)) == 0) {
            printf("Client Exit...\n");
        }
    }
}

int create_client(void* arg){
int sockfd, connfd;
    struct sockaddr_in servaddr, cli;

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully created..\n");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    servaddr.sin_port = htons(PORT);

    // connect the client socket to server socket
    if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
        printf("connection with the server failed...\n");
        exit(0);
    }
    else
        printf("connected to the server..\n");

    // function for chat
    client_func(sockfd);

    // close the socket
    
    close(sockfd);
    
    return 0;
    
}

// Driver function
int main()
{
    int sockfd, connfd, len;
    struct sockaddr_in servaddr, cli;
    thrd_t client_thrd_handle;

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully created..\n");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    servaddr.sin_port = htons(PORT);

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully binded..\n");

//creating client on sepearte thread
    thrd_create(&client_thrd_handle,create_client,NULL);

    // Now server is ready to listen and verification
    if ((listen(sockfd, 5)) != 0) {
        printf("Listen failed...\n");
        exit(0);
    }
    else
        printf("Server listening..\n");
    len = sizeof(cli);

    // Accept the data packet from client and verification
    connfd = accept(sockfd, (SA*)&cli, &len);
    if (connfd < 0) {
        printf("server accept failed...\n");
        exit(0);
    }
    else
        printf("server accept the client...\n");

 func(connfd);

    // After chatting close the socket
    close(sockfd);
    thrd_join(client_thrd_handle,NULL);
}

commented May 21, 2022 by xDELLx (10,500 points)
On second thoughts , i think running server & client of 2 separate threads would do the trick.
Irrespective of loop-back address, i thnik!!
Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...