0

I am attempting to implement a client-server network. I am following Beej's Guide to Network Programming

My program scans an input from the keyboard, looks up the associated value in an array then sends a GET request to my server via UDP. However, it appears that my server is not receiving my request.

This is my client code excerpt:

    // loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) {
        perror("talker: socket");
        continue;
    }

    break;
}

if (p == NULL) {
    fprintf(stderr, "talker: failed to bind socket\n");
    return 2;
}

printf("Please Enter Your Search (USC, UCLA etc.):");
char searchKey[5];
fgets(searchKey, sizeof(searchKey), stdin);
int len, bytes_sent;
char value[8];
len = strlen(value);
char request[10];
for(int i = 0; i < sizeof(clientMap) / sizeof(struct Mapping); i++) {
  if (strcmp(clientMap[i].key, searchKey) == 0) {
    //value = clientMap[i].value;
    memcpy(value, clientMap[i].value, sizeof(char) * 6);
    strcat(request, "GET ");
    strcat(request, value);
    break;
  }
}
printf("The Client 1 has received a request with search word %s, which maps to key %s\n", searchKey, value);
printf("The Client 1 sends the request %s to the Server 1 with port number %s and IP address %s\n", request, SERVERPORT, argv[1]);
printf("The Client1's port number is TODO and the IP address is TODO\n");
if ((numbytes = sendto(sockfd, request, strlen(request), 0,
         p->ai_addr, p->ai_addrlen)) == -1) {
    perror("talker: sendto");
    exit(1);
}

freeaddrinfo(servinfo);

printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);

This is my server excerpt:

// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) {
        perror("listener: socket");
        continue;
    }

    if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
        close(sockfd);
        perror("listener: bind");
        continue;
    }

    break;
}

if (p == NULL) {
    fprintf(stderr, "listener: failed to bind socket\n");
    return 2;
}

freeaddrinfo(servinfo);

printf("listener: waiting to recvfrom...\n");

addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
    (struct sockaddr *)&their_addr, &addr_len)) == -1) {
    perror("recvfrom");
    exit(1);
}

buf[numbytes] = '\0';
printf("The Server 1 has received a request with key %s\n", buf);
for(int i = 0; i < sizeof(serverMap) / sizeof(struct Mapping); i++) {
  if (strcmp(serverMap[i].key, buf) == 0) {
    char post[13];
    strcpy(post, "POST ");
    strcat(post, serverMap[i].value);
    printf("The Server 1 sends the reply %s to TODO: Finish this!", post);
    sendto(sockfd, post, strlen(post), 0, (struct sockaddr *)&their_addr, addr_len);
    break;
  }
}
close(sockfd);

I know that the problem is that my server is not receiving the datagram. I imagine I am making some obviously easy mistake, but my understanding of C and Networks is not so strong.

On a side note, you may notice that my print statements contain TODOs. I am unsure how to grab these IP addresses and port numbers. Can someone also help with this?

Brian
  • 7,098
  • 15
  • 56
  • 73
  • 1) `len = strlen(value);` value is uninitialized 2) `if (strcmp(clientMap[i].key, searchKey) == 0) {` searchkey possibly still has an '\n' at the end (unless the entered string had length==4) – wildplasser Apr 06 '15 at 19:32
  • 1
    server is maybe not binded to a port. how are you going to send if you don't know to which ip and which port ? I don't follow why you have that loop and what is in the p linked list datastructure matters greatly. – Philip Stuyck Apr 06 '15 at 19:34
  • @PhilipStuyck The server is binded in code that I did not include. Sorry. Also, if I understood Beej's guide correctly, the loop is an attempt to loop through all the returned results and bind to the first one that we can. Beej seemed to emphasize that there are some older and newer ways of coding this – Brian Apr 06 '15 at 19:41
  • 1
    I don't know Beej, but a server that is iterating over a list of ports and or ip addresses is just strange. – Philip Stuyck Apr 06 '15 at 19:42

1 Answers1

1

Your server needs anyhow a fixed port to listen on. How are you going to expect your client to know to which port it is supposed to send ? Just use an arbitrary port on both the server and the client.

Since you are new at this, try everything locally at first. The server should listen to INADDR_ANY and the arbitrary port that you choose.

Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39
  • @Phillip I define the port on the client and server side with `#define MYPORT "21474"` But I think I see your point. It appears that my server binds but my client does not. I am trying your suggestion now by copying `if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("listener: bind"); continue; }` into my client code – Brian Apr 06 '15 at 19:44
  • the client does not need to bind. It uses sendto and in the address parameter should be the same port as the one you define in your server and the servers ip@, but if you run locally that is 127.0.0.1 not in dotted notation of course. – Philip Stuyck Apr 06 '15 at 19:53
  • btw don't forget htons for the ports and htonl for the ip addresses. – Philip Stuyck Apr 06 '15 at 19:54