0

I am developing a TCP handshake between a client and a server. In the specific the client send a message to the server, the server analyze the message and provide an answer. The problem is that it seems that when the server has to send back the message there are some problems, i.e the client and the server are blocked.

That is my code Client side:

    if (connect(sock, (struct sockaddr *) &server_addr, sizeof(struct sockaddr))
        == -1) {
    perror("Connect");
    exit(1);
}
char recv_data[2048];
first_message(user, mode, sock);
    do {
        bytes_recieved = recv(sock, recv_data, 1024, 0);
        if (bytes_recieved == -1) {
            printf("Error");
            exit(1);
        }
        printf("BYTE RECEIVED: %d\n", bytes_recieved);
    } while (bytes_recieved != 0);
    recv_data[bytes_recieved] = '\0';
    printf("%s", recv_data);

Server side:

    sin_size = sizeof(struct sockaddr_in);

    connected = accept(sock, (struct sockaddr *) &client_addr, &sin_size);

    printf("\n I got a connection from (%s , %d)",
            inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    char recv_data[2048];
    do {
        res = length_true - total;
        bytes_recieved = recv(connected, recv_data + total, res, 0);
        if (bytes_recieved == -1) {
            printf("Recv() failed\n");
            break;
        }
        if (bytes_recieved > 0) {
            total += bytes_recieved;
        }
    } while (bytes_recieved != 0);
    int size_rcv = total;
    recv_data[length_true - 1] = '\0';
    int b = 0;
    printf("DATA RECEIVED:%s\n", recv_data);
    send(connected,r,strlen(r),0);
    fflush(stdout);
    close (sock);
    exit(1);
    pause();
    return 0;

Edit:

void common_frame(int sock, char *mode) {

    const char *string_course = "DISTRIB2016";
    char *buf = (char*) malloc(22 * sizeof(char));
    char *buf_first = (char*) malloc(2 * sizeof(char));
    gethexes(buf_first, mode); //1 byte di modalità
    gethexes(buf, string_course); //11 byte lunghezza del corso stringa
    send(sock, buf, 22, 0);
    send(sock, buf_first, 2, 0);
    free(buf_first);
    free(buf);
}

void first_command(int sock, char* user) {
    char *frame = "T1";
    char *buf_second = (char*) malloc(4 * sizeof(char));
    char *username_length = (char*) malloc(sizeof(char));
    int user_len = strlen(user);
    char *us = (char*) malloc(user_len *2 * (sizeof(char)));
    gethexes(us, user);
    gethexes(buf_second, frame); //2 byte of first command label T1
    sprintf(username_length, "%d", user_len);
    send(sock, buf_second, 4, 0);
    send(sock, username_length, strlen(username_length), 0); //n byte username length
    send(sock, us, strlen(us), 0); //username
    free(username_length);
    free(buf_second);

}

void first_message(char *user, char*mode, int sock) {
    unsigned short int message_length;
    char *length;
    int user_len;
    message_length = htons(17 + strlen(user));
    length = decimal_to_binary(message_length); //2 byte di lunghezza binaria in network order
    send(sock, length, strlen(length), 0);
    common_frame(sock, mode);
    first_command(sock, user);
}

With this implementation both client and server are stop and the server cannot receive any message, but if I stop the client magically the server works and It receives and send the data correctly.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 4
    With this implementation and without seeing what `first_message()` does, all you can possibly get is a deadlock while both sides wait for input from each other, in loops that can't terminate until the peer closes the connection. – user207421 Apr 12 '16 at 08:06
  • 4
    You do know that sockets are by default *blocking*, and if there's no data to read then the `recv` calls will block. Without knowing what your `first_message` function does, it seems like both programs are simply waiting for data to be received. – Some programmer dude Apr 12 '16 at 08:07
  • 4
    Using `select` function before reading on a socket will tell you if something is ready to be read. – Mathieu Apr 12 '16 at 08:09
  • 1
    Also, your receive loop in the client is flawed. If the socket it blocking, then once you receive anything and there is no errors or closed connections, you will continue to read all the data until there is no more data to read, and the call will again block. In practice, an infinite loop until you get an error or a disconnection. You will also overwrite the data you read in the previous iteration. – Some programmer dude Apr 12 '16 at 08:10
  • 1
    The server loop waits for a disconnect. The client does not appear to disconnect anywhere. Server stuck forever. This is what happens when you use connect/disconnect protocol and use it incorrectly. – Martin James Apr 12 '16 at 08:12
  • 2
    Using select is a red herring. select blocks too, and the OP's issue is that of misuse of connect/disconnect protocol, not any problem with blocking. EJP had it right with 1st comment. – Martin James Apr 12 '16 at 08:14
  • @EJP I edited my solution adding the first_message. How should I do? – Federico Pagano Apr 12 '16 at 08:16
  • `select` is needed when you want to handle several clients simultaneously in a single thread. – Klas Lindbäck Apr 12 '16 at 08:40
  • @KlasLindbäck When you are using non-blocking mode. No evidence of any of that here. – user207421 Apr 12 '16 at 09:31
  • @EJP The question only mentions a single client. Part of the problem seems to be the lack of a message protocol. – Klas Lindbäck Apr 12 '16 at 09:51
  • 2
    @KlasLindback Exactly, so `select()` isn't indicated. The lack of an application protocol seems to be the *entire* problem here, or else a misapprehension a stonwhrn`recv()` returns zero. – user207421 Apr 12 '16 at 09:58

1 Answers1

3

As stated in comments, your server does nothing until recv() returns zero or -1, which mean the client has disconnected or aborted the connection respectively. As your client does neither of those things, you have an application-induced deadlock.

user207421
  • 305,947
  • 44
  • 307
  • 483