2021年2月7日星期日

In c, TCP sockets hangs and behave strange when sending data

I'm trying to implement TCP sockets where the client sends some data to the server and receives a response from the server. But right now my codes seem stuck at receiving data at the server.

This is my code for the server:

#define MAX_INPUT_SIZE    4000  #define EXIT_NOT_ON_VALUE(expression, value, message,exit_status) \      if ((expression)!=(value)) {\          fprintf(stderr,(message));\          exit((exit_status));\      }    int main(int argc, char **argv){      int status, server_socket, client_number = 1;         struct sockaddr_in address, client_address;      int client_address_size;        address.sin_family = AF_INET;      address.sin_port = htons(argv[1]);      address.sin_addr.s_addr = htonl(INADDR_ANY);        server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);      EXIT_ON_VALUE(server_socket, -1, "SOCKET CREATION FAILED, EXIT.\n", EXIT_FAILURE);        status = bind(server_socket, (SA*)&address, sizeof(address));      EXIT_ON_VALUE(status, -1, "BIND FAILED, EXIT.\n", EXIT_FAILURE);        status = listen(server_socket, MAX_LIS_QUEUE);      EXIT_ON_VALUE(status, -1, "LISTEN CREATION FAILED, EXIT.\n", EXIT_FAILURE);        while(1){          struct sockaddr_in client_address;          socklen_t address_size;            int client = accept(server_socket, (SA*)&client_address, &address_size);          if (client==-1 && errno == EINTR) continue;          EXIT_ON_VALUE(client, -1, "ACCEPT FAILED, EXIT.\n", EXIT_FAILURE);                         fprintf(stderr, "Accepted.  Client No: %d.  File No: %d\n",                   client_number, client);            int child_pid = fork();          EXIT_ON_VALUE(child_pid, -1, "CHILD PROCESS CREATION FAILED, EXIT.\n", EXIT_FAILURE);            if(child_pid==0){              char *row = malloc(MAX_INPUT_SIZE);              EXIT_ON_VALUE(row, NULL, "CANNOT ALLOCATE MEMORY, EXIT. \n", EXIT_FAILURE);              status = read_in_full(client, row, 20);              EXIT_ON_VALUE(status, -1, "CANNOT READ, EXIT. \n", EXIT_FAILURE);                printf("row data is:%s\n", row);                /* modifying data operations... */                close(client);              exit(EXIT_SUCCESS);          }          int result;          wait(&result);          char *msg = "NO PROBLEM!";            status = write_in_full(client, msg, strlen(msg));        }      close(server_socket);      exit(EXIT_SUCCESS);  }  

This my code for the client:

#define MAX_INPUT_SIZE  4000    int main(int argc, char **argv) {      int status;        int connection;      struct sockaddr_in address;        char* data=malloc(4000);      char* response=malloc(4000);              printf("Data goes in?\n");      fgets(data, MAX_INPUT_SIZE, stdin);      if ((strlen(data)>0) && (data[strlen(data)-1]=='\n'))          data[strlen(data)-1] = '\0';      while (getchar()!='\n')          ;            address.sin_family = AF_INET;      address.sin_port = htons(argv[1]);      address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);        connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);      EXIT_ON_VALUE(connection, -1, "Failed to create socket", EXIT_FAILURE);        printf("FD is: %d\n", connection);        status = connect(connection, (SA*) &address, sizeof(address));      EXIT_ON_VALUE(status, -1, "Connection failure", EXIT_FAILURE);        status = write_in_full(connection, data, strlen(data));      if (status != -1) printf("Data sent!\n");        read_in_full(connection, data, MAX_INPUT_SIZE);        printf("Response was %s\n", response);               close(connection);      exit(EXIT_SUCCESS);      }  

Both read_in_full and write_in_full are functions try to avoid signal interrupt, they are implemented as follows:

int read_in_full(int fd, void *data, size_t size) {      size_t total_read = 0;      fprintf(stderr, "READING data.\n");        while (total_read < size) {            int n_read = read(fd, data + total_read, size - total_read);          if (n_read == -1) {              if (errno == EINTR)                  continue;              else                  return -1;              }            total_read += n_read;            if (n_read == 0)              return total_read;          }        return total_read;      }    int write_in_full(int fd, void *data, size_t size) {      size_t total_written = 0;        while (total_written < size) {          int n_written = write(fd, data + total_written, size - total_written);          if (n_written == -1) {              if (errno == EINTR)                  continue;              else                  return -1;              }            total_written += n_written;          }        return total_written;      }  

What happened is:

  1. I start running the server, and it runs fine if there aren't any errors.
  2. I start running the client, and Accepted. Client No: 1. File No: 4 shows up which means my client has successfully connected to the server.
  3. The client would print Data goes in? and allow me to input a line of strings.
  4. The client would print Data sent!, and both server and client would print READING data. which means they are calling the read_in_full() function and seems working.
  5. Server stuck at this point. It doesn't read from the socket. At the main time, the client is waiting for a response.
  6. I closed the server with ctrl+c and the client will print Response was, obviously it doesn't receive anything.

This behaviour is so weird. Could someone help me on this, I'm so confused.

Thanks and appreciate!

https://stackoverflow.com/questions/66095024/in-c-tcp-sockets-hangs-and-behave-strange-when-sending-data February 08, 2021 at 09:58AM

没有评论:

发表评论