Search code examples
csocketsstrcmp

C program hanging near strcmp


I am building a client-server socket simulation in C I accept a TCP connection from a client then the client sends a message to my server. I am successfully receiving the message, then I iterate through my array of structs to look for a string match

struct Mapping
{
  char  key[6];
  char  value[8];
} MapElement;

int main
{
  char buf[BUFSIZE]; /* BUFSIZE 2048 */
  int size = 4;
  struct Mapping serverMap[size];
  initialize_server_map(serverMap); /* This method works, so not displaying in SO */

  /* ... socket stuff (this works as seen from print statements) */

  recvlen = recv(rqst, buf, BUFSIZE, 0);
  printf("The received length is %d\n", recvlen);
  printf("The buf is: %s\n", buf);
  if (recvlen > 0) {
    buf[recvlen] = 0;
    printf("The Server 2 has received a request with key %s\n", buf);
    char* buf_for_token[10];
    strcpy(buf_for_token, buf);
    const char s[2] = " ";
    char *token;
    token = strtok(buf_for_token, s);
    token = strtok(NULL, s);
    int found = 0;
    for(int i = 0; i < sizeof(serverMap) / sizeof(struct Mapping); i++) {
      printf("Token: %sServerMapEntry: %s\n", token, serverMap[i].key);
      printf("Compare: %d\n", strcmp(serverMap[i].key, token));
      if (strcmp(serverMap[i].key, token) == 0) {
        printf("What is wrong?!?! Why is this not printing?!\n");
        found = 1;
        strcpy(post, "POST ");
        strcat(post, serverMap[i].value);
        if (send(rqst, post, strlen(post), 0) < 0) {
          perror("sendto");
        }
        break;
      }
    }
  }
}

My output is:

The received length is 9
The buf is: GET key05
The Server 2 has received a request with key GET key05
Token: key05ServerMapEntry: key05
Compare: 0

I cannot understand why the next print statement is not printing. My program is just hanging forever. :(


Solution

  • There is a bug here:

    char* buf_for_token[10];
    strcpy(buf_for_token, buf);
    

    How do you manage to even compile this program? buf_for_token is an array of pointers to char, it should just be an array of char, and make it large enough:

    char buf_for_token[BUFSIZE];
    strcpy(buf_for_token, buf);
    

    This buffer should be as large as the receiving buffer, and as mentioned in the comments, you should pass 1 less than its size to recv in order to keep one extra byte for the '\0' you force at the end:

    recvlen = recv(rqst, buf, sizeof(buf) - 1, 0);
    

    In the for loop, use size instead of sizeof(serverMap) / sizeof(struct Mapping), or sizeof(serverMap) / sizeof(*serverMap).

    As to why the printf("What is wrong?!?! Why is this not printing?!\n"); does not output anything, try fflush(stdout); just after the printf() to make sure it is not just a buffering issue.

    Or it may also be that you are not posting the exact code... post is not defined, and the function prototype is missing some body parts:

    int main
    {
    

    Finally, if your sockets are TCP, be aware that data sent by the client may be received by the server in chunks of a different size, smaller of larger. The only guarantee is the order of the byte stream. You should not rely on the fact that most of the time you receive a full line. Network congestion or other conditions beyond yoyr control may cause packets to get sliced and received in small chunks or combined in larger chunks containing several lines... To handle this potential situation in the server you should bufferize the data and handle one line at a time.