Search code examples
csocketstcpsend

Socket C handle recv() and send() at the same time


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.


Solution

  • 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.