Thread: problems with client server achitecture: client does not wait the reply of the server

  1. #1
    Registered User
    Join Date
    Aug 2018
    Posts
    7

    problems with client server achitecture: client does not wait the reply of the server

    Good evening,
    I would like to ask your help. I work in Windows 10 with Visual Studio.

    I would like to write a piece of software (Soft1) that receives text messages from a program (Soft2) and depending on the message received sends a text message to another program (Soft3).

    Soft3 is already available, I am writing Soft1 and Soft2.

    my idea is to use a server client architecture. Soft1 will create a server socket, waits for incoming connection (from Soft2) and after Soft2 is connected creates another client socket and connects to Soft3.
    Soft 2 will create a client socket, connect to Soft1and start to send messages. Soft2 should send a message, wait for the reply and then send the next message.

    To keep it simple, in this first version Soft1 should just forward messages from Soft2 to Soft3 and forward back the reply from Soft3 to Soft2 till a specific message (Mes1) is received. In order to identify the incoming messages, Soft1 looks at the first 4 characters and compares them with some test strings (Mes1, Mes2,...).

    I start the execution of Soft1, then I start the execution of Soft2. Soft2 can create the client socket and send a first message to Soft1 and wait for a reply before sending a second message to Soft1. Till this point everything is ok.
    The problem arrives after the second message sent by Soft2: Soft2 does not wait for the reply of Soft 1 and send immediately the other messages.
    I writes here the codes for Soft1 and Soft2 that create problems (I did not put the part that creates the sockets because it works).

    Soft1
    Code:
    #include <stdio.h>
    #include <winsock2.h>
    # include <WS2tcpip.h>
    # include <iphlpapi.h>
    
    
    #include <windows.h>
    
    #pragma comment(lib, "ws2_32.lib")
    int main(int argc, char *argv[])
    {
    
    /*Initialize Winsock*/
    
    /*Create a TCP Socket: for server communication with Soft2 */
    
    //Bind
    
    //listen to incoming connection
    
    //Accept connection
    
    c = sizeof(struct sockaddr_in);
        Soft2 = accept(new_socket, (struct sockaddr *)&client, &c);
    
        if(new_socket == INVALID_SOCKET)
        {
            printf("Accept failed : %d", WSAGetLastError());
        }
    
        puts("Connection accepted");
    
    /*Create a TCP Socket for connecting to Soft3*/
    
    /*Connect to Soft3 server*/
    
    if (connect(Soft3, (struct sockaddr *)&serverSoft3, sizeof(serverIPG)) < 0)
        {
            //puts("connect error");
            printf("Connect Error : %d \n", WSAGetLastError());
            return 1;
        }
    
    /*Start of the while loop that receives and forwards messages*/
    
    char Test[] = "xxxx";
    Mes1[] = "Mes1";
    Mes2[] = "Mes2";
    Mes3[] = "Mes3";
    
    While (1)
    {
    Test[0] = 'p';
    
            while (strcmp(Test, Mes1) != 0)
    {
    if ((recv_size = recv(Soft2, server_reply, 2000, 0)) == SOCKET_ERROR)     
                {
                             return 1;
                }
                else
    
                {
                    memcpy(Test, server_reply, 4);
                    counter++;
    printf("received message %d \n", counter);
    
    if (send(Soft3, server_reply, strlen(server_reply), 0) < 0)
                    {
                       
                        return 1;
                    }
                    printf("Sent message to Soft3 %d \n", counter);
    
    if ((recv_size = recv(Soft3, server_reply2, 2000, 0)) == SOCKET_ERROR)
                    {
                                            return 1;
                    }
                    printf("Received reply from Soft3 %d \n", counter);
                    if (send(Soft2, server_reply2, strlen(server_reply2), 0) < 0)
                    {
                       
                        return 1;
                    }
    
                    printf("Sent to Soft2 reply by Soft3 %d \n", counter);
    }
    
    }
    
    
    }
        closesocket(Soft2);
        closesocket(Soft3);
        WSACleanup();
        return 0;
    }
    Soft2:

    Code:
    #include <stdio.h>
    #include <winsock2.h>
    # include <WS2tcpip.h>
    # include <iphlpapi.h>
    
    
    #include <windows.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main(int argc, char *argv[])
    {
        /*Initialize Winsock*/
    
    /*Create a TCP Socket */
    
    /*Connect to a server*/
    
    if (connect(Soft1, (struct sockaddr *)&server, sizeof(server)) < 0)
        {
           
            printf("Connect Error : %d", WSAGetLastError());
            return 1;
        }
    /*Send message 1*/
        
        message = "Mes2 do something \n"; 
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
    
    
    /* Receive reply for message 1*/
    
    /*at the following "if" Soft2 stops correctly and wait for Soft1 reply*/
    
    if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
        {
            puts("Reception failed0");
            return 1;
        }
    
    /*Send message 2*/
    
        message = "Mes2 do something \n"; 
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
    
    /* Receive reply for message 2*/
    
    /*here Soft2 does not stop correctly and does not wait for Soft1 reply, as Soft2 could still read the reply from the previous message 1, and sends message 3*/
    /*Soft1 then will receive message 2 and message 3 together   */
    
    if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
        {
            puts("Reception failed0");
            return 1;
        }
    
    /*Send message 3*/
    
        message = "Mes3 do something \n"; 
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
    
    if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
        {
            puts("Reception failed");
            return 1;
        }
    
    /*Send message 4*/
    
        message = "Mes1 stop the While loop \n"; 
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
    return 0;
    }
    I would like to ask you what is the correct manner to write Soft1 so that Soft2 waits the arriving of a reply before sending the next message.
    thank you!

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    1. Fix your indentation, so people might care to look at your code.
    Indentation style - Wikipedia

    2. Post something which actually compiles, not with bits chopped out because you believe them to be irrelevant (they work for me).
    For example
    - While (1)
    C is case sensitive, so this doesn't compile.
    - if ((recv_size = recv(Soft1, server_reply, 2000, 0))
    Do we take it on trust that server_reply is a suitable block of memory.

    > /*here Soft2 does not stop correctly and does not wait for Soft1 reply, as Soft2 could still read the reply from the previous message 1, and sends message 3*/
    > /*Soft1 then will receive message 2 and message 3 together */
    > if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
    You need to understand that TCP connections are streams (like files or pipes). You write stuff at one end, and read it at the other.
    The big problem is that you're assuming that if you write "hello" at one end, that the other end will atomically read "hello". This is simply NOT true.

    It is YOUR responsibility to arrange the messages such that the receiver can reconstruct the data.
    For example, every line is printable characters ending with '\n'.

    The receiver then knows to call recv() in a loop until \n is received, then pass the resulting message back up the call chain.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Aug 2018
    Posts
    7
    Hello Salem,
    thank you for your reply and your suggestions, I hope that this time the indentation will not be lost, now all the code is written (end of this reply).

    Quote Originally Posted by Salem View Post

    You need to understand that TCP connections are streams (like files or pipes). You write stuff at one end, and read it at the other.
    The big problem is that you're assuming that if you write "hello" at one end, that the other end will atomically read "hello". This is simply NOT true.

    It is YOUR responsibility to arrange the messages such that the receiver can reconstruct the data.
    For example, every line is printable characters ending with '\n'.

    The receiver then knows to call recv() in a loop until \n is received, then pass the resulting message back up the call chain.
    I understand your point, but what it is still not clear to me is why at the first

    Code:
    if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
    Soft2 waits correctly while after does not stop. I can see it if I execute Soft1 in debugging mode line by line: Soft2 sends the other messages when Soft1 has not sent yet the new reply.


    Soft1
    Code:
    #include <stdio.h>
    #include <winsock2.h>
    #include <WS2tcpip.h>
    #include <iphlpapi.h>
    #include <windows.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main(int argc, char *argv[])
    {
        int recv_size, counter;
        char server_reply[1000], server_reply2[1000];
        /*Initialize Winsock*/
        WSADATA wsa;
        SOCKET Soft2, Soft3, new_socket;
        struct sockaddr_in server, client, serverSoft3;
    
    
        /*Create a TCP Socket: for server communication with Soft2 */
        printf("\nInitialising Winsock");
        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) //MAKEWORD(2,2) parameters of WSAStartup makes a request for version 2.2 of Winsock
        {
            printf("Failed, error code: %d", WSAGetLastError());
            return 1;
        }
    
        printf("Initialised \n");
    
        /*Create a TCP Socket: for server communication with Soft2 */
    
        if ((new_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) /* Look at documentation: docs.microsoft.com/en-gb/windows/desktop/api/winsock2/nf-winsock2-socket */
        {
            printf("Couldn't create Socket : %d", WSAGetLastError());
        }
    
        printf("Socket created \n");
    
        //Prepare sockaddr in structure
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons(15000);
    
        //Bind
        if (bind(new_socket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
        {
            printf("Bind Error : %d", WSAGetLastError());
        }
    
        puts("Bind ok");
    
        //listen to incoming connection
        listen(new_socket, 3);
    
        //Accept connection
        puts("Waiting for incoming connections");
    
        int c = sizeof(struct sockaddr_in);
    
        Soft2 = accept(new_socket, (struct sockaddr *)&client, &c);
    
        if (new_socket == INVALID_SOCKET)
        {
            printf("Accept failed : %d", WSAGetLastError());
        }
    
        puts("Connection accepted");
    
    
    
        /*Create a TCP Socket for connecting to Soft3*/
    
        if ((Soft3 = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) /* Look at documentation: docs.microsoft.com/en-gb/windows/desktop/api/winsock2/nf-winsock2-socket */
        {
            printf("Couldn't create Socket : %d", WSAGetLastError());
        }
    
        printf("Socket created \n");
    
    
        /*Connect to Soft3 server*/
        char address[] = "127.0.0.1";
    
        char *addP = address;
    
        unsigned long *p;
    
        p = malloc(4);
    
        inet_pton(AF_INET, addP, p);
    
        serverSoft3.sin_addr.s_addr = *p;
    
    
        serverSoft3.sin_family = AF_INET;
        serverSoft3.sin_port = htons(2000);
    
        if (connect(Soft3, (struct sockaddr *)&serverSoft3, sizeof(serverSoft3)) < 0)
        {
            //puts("connect error");
            printf("Connect Error : %d \n", WSAGetLastError());
            return 1;
        }
    
        /*Start of the while loop that receives and forwards messages*/
    
        char Test[] = { "xxxx" };
        char Mes1[] = { "Mes1" };
        char Mes2[] = { "Mes2" };
        char Mes3[] = { "Mes3" };
        counter = 0;
    
        while(1)    {
            Test[0] = 'p';
    
            while (strcmp(Test, Mes1) != 0)
            {
                if ((recv_size = recv(Soft2, server_reply, 2000, 0)) == SOCKET_ERROR)
                {
                    return 1;
                }
                else
    
                {
                    memcpy(Test, server_reply, 4);
                    counter++;
                    printf("received message %d \n", counter);
    
                    if (send(Soft3, server_reply, strlen(server_reply), 0) < 0)
                    {
    
                        return 1;
                    }
                    printf("Sent message to Soft3 %d \n", counter);
    
                    if ((recv_size = recv(Soft3, server_reply2, 2000, 0)) == SOCKET_ERROR)
                    {
                        return 1;
                    }
                    printf("Received reply from Soft3 %d \n", counter);
                    if (send(Soft2, server_reply2, strlen(server_reply2), 0) < 0)
                    {
    
                        return 1;
                    }
    
                    printf("Sent to Soft2 reply by Soft3 %d \n", counter);
                }
    
            }
    
    
        }
        closesocket(Soft2);
        closesocket(Soft3);
        WSACleanup();
        //return 1;
    }
    Soft2:

    Code:
    #include <stdio.h>
    #include <winsock2.h>
    #include <WS2tcpip.h>
    #include <iphlpapi.h>
    #include <windows.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main(int argc, char *argv[])
    {
        /*Initialize Winsock*/
        WSADATA wsa;
        SOCKET Soft1;
        struct sockaddr_in server;
        char *message, server_reply[2000];
        int recv_size;
    
        printf("\nInitialising Winsock \n");
        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) //MAKEWORD(2,2) parameters of WSAStartup makes a request for version 2.2 of Winsock
        {
            printf("Failed, error code: %d", WSAGetLastError());
            return 1;
        }
    
        printf("Initialised \n");
    
        /*Create a TCP Socket */
    
        if ((Soft1 = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) /* Look at documentation: docs.microsoft.com/en-gb/windows/desktop/api/winsock2/nf-winsock2-socket */
        {
            printf("Couldn't create Socket : %d", WSAGetLastError());
        }
    
        printf("Socket created \n");
    
        /*Connect to a server*/
    
        char address[] = "127.0.0.1";
    
        char *addP = address;
    
        unsigned long *p;
    
        p = malloc(4);
        
        inet_pton(AF_INET, addP, p);
    
        server.sin_addr.s_addr = *p;
    
    
        server.sin_family = AF_INET;
        server.sin_port = htons(15000);
    
        if (connect(Soft1, (struct sockaddr *)&server, sizeof(server)) < 0)
        {
    
            printf("Connect Error : %d", WSAGetLastError());
            return 1;
        }
        /*Send message 1*/
    
        message = "Mes2 do something \n";
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
        
        /* Receive reply for message 1*/
    
        /*at the following "if" Soft2 stops correctly and wait for Soft1 reply*/
    
        if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
        {
            puts("Reception failed0");
            return 1;
        }
    
        /*Send message 2*/
    
        message = "Mes2 do something \n";
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
    
        /* Receive reply for message 2*/
    
        /*here Soft2 does not stop correctly and does not wait for Soft1 reply, as Soft2 could still read the reply from the previous message 1, and sends message 3*/
        /*Soft1 then will receive message 2 and message 3 together   */
    
        if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
        {
            puts("Reception failed0");
            return 1;
        }
    
        /*Send message 3*/
    
        message = "Mes3 do something \n";
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
    
        if ((recv_size = recv(Soft1, server_reply, 2000, 0)) == SOCKET_ERROR)
        {
            puts("Reception failed");
            return 1;
        }
    
        /*Send message 4*/
    
        message = "Mes1 stop the While loop \n";
    
        if (send(Soft1, message, strlen(message), 0) < 0)
        {
            puts("Send failed");
            return 1;
        }
        return 0;
    }

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Some more broken things in your code.

    recv() does NOT append a \0 to whatever is received, so your attempts at using strlen, strcpy etc will fail.

    Some of your 2000 buffer lengths are referring to buffer sizes of 1000 (this is bad!).

    A better recv would be
    Code:
    int myrecv( int sock, char *buff, size_t buffsize ) {
      int recv_size = recv(sock, buff, buffsize-1, 0);
      if ( recv_size >= 0 ) {
        // make a valid result into a valid string.
        buff[recv_size] = '\0';
      }
      return recv_size;
    }
    > listen(new_socket, 3);
    > server.sin_port = htons(15000);
    > serverSoft3.sin_port = htons(2000);
    Make these constants in your code.
    That goes for most of the magic numbers you have peppered through the code.

    > char address[] = "127.0.0.1";
    > char *addP = address;
    Things like this add no value. Just remove addP and use address directly.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Aug 2018
    Posts
    7
    Salem,
    thank you for your time and your suggestions, now the code runs better
    kind regards
    ALberto

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple Client - Server problems (Async Sockets )
    By Cpp_Noob in forum Networking/Device Communication
    Replies: 4
    Last Post: 06-19-2009, 07:12 AM
  2. Client/server problem; server either stops receiving data or client stops sending
    By robot-ic in forum Networking/Device Communication
    Replies: 10
    Last Post: 02-16-2009, 11:45 AM
  3. facing problems in setting up NFS server/client
    By kris.c in forum Tech Board
    Replies: 0
    Last Post: 12-19-2006, 10:12 PM
  4. how we can get client id in server
    By cnu_sree in forum Networking/Device Communication
    Replies: 1
    Last Post: 09-04-2006, 05:14 AM
  5. Chat Client/Server Problems
    By _Cl0wn_ in forum C++ Programming
    Replies: 2
    Last Post: 05-25-2003, 11:38 AM

Tags for this Thread