0

I've managed to create a C server that accepts a connection from a web browser, however, the HTTP request I receive from the socket is random bytes that I can't seem to convert to ASCII values, as below:

\00\00\00\00\00\00\00\00\A9Ag_\BD\00\00\00\00\00\00\00\00\00\00\BD\88_\BD\00\00\C0\B4\88_\BD\00\00<\A7f_\BD\00\00\F0,+_\BD\00\00\A4f_\BD\00\00\00\00\00\00\00\00\00\9D\00\00\00\00\00\00\00\00\00\00\00\000b0\D8\FF\00\00\90a0\D8\FF\00\00\BD\88_\BD\00\00\C0\E5\88_\BD\00\00\F8و_\BD\00\00\00\00\00\00\00\00\00\A9Ag_\BD\00\00\00\00\00\00\00\00\00\00\BD\88_\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\00\00\F8و_\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\F8\E7\88_\BD\00\00(`\00\00\00\00\00\00\00\00\00\00\00\00\00\C0\E5\88_\BD\00\00\F0`0\D8\FF\00\00\E0`0\D8\FF\00\00\87\F0\96|\00\00\00\00\00\00\80\C0\00\00\00\00\00\90-Ͼz\FF<\A7f_\BD\00\00\FF\FF\FF\FF\00\00\00\00\00 *_\BD\00\00\D0++_\BD\00\00\C0\B4\88_\BD\00\00 <\00\00\00\00\00\C0\B4\88_\BD\00\00\B0b0\D8\FF\00\00\FD\A6=_\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\C0\E1?\D8\FF\00\00\00\00\00\00 \00\00\00|6g_\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00c0\D8\FF\00\00\00\00\00\00\00\00\00&\B0be\00\00\00\00*?g_\BD\00\00\00\00\00\00\00\00\00\00&\00\00\00\00\00\00\00\C0\8A\95\00\00\00\00`\E1?\D8\FF\00\00\00\00\00\BD\00\00\00\00\00\00\00\00\00\00`\E1?\D8\FF\00\00|6g_\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00pc0\D8\FF\00\00\00\00\00\00\00\00\00.N=\F6\00\00\00\00\80>g_\BD\00\00\00\00\00\00\00\00\00\00.\00\00\00\00\00\00\008\F5\D8\00\00\00\00]*_\BD\00\00[*_\BD\00\00\00\00\00\00\00\00\00]*_\BD\00\00\C8c0\D8\FF\00\00\A0c0\D8\FF\00\00 !+_\BD\00\00\80\EB\88_\BD\00\00\F8\E7\88_\BD\00\00\00\00\00\00\00\00\00\00\BA\88_\BD\00\00\C0\B4\88_\BD\00\00\D4@\00\00\00\00\00\F0,+_\BD\00\00\80@\00\00\00\00\00\00\00\00\00\00\00\00+\00\00\00\00\00h\E2\88_\BD\00\008d0\D8\FF\00\00d0\D8\FF\00\00\BA\88_\BD\00\00\C0\E5\88_\BD\00\00h\E2\88_\BD\00\00\00\00\00\00\00\00\00\A9Ag_\BD\00\00\00\00\00\00\00\00\00\00\BA\88_\BD\00\00\00\00\00\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00h\E2\88_\BD\00\00\D8\E1?\D8\FF\00\00\F8\E7\88_\BD\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\C0\E5\88_\BD\00\00pc0\D8\FF\00\00`c0\D8\FF\00\00.N=\F6\00\00\00\00v\00\00\00\00\00\00\C2\00\00\00\00\00\00\00\D4@\00\00\00\00\00\F

To be fair, when in terminal, it does seem to "resemble" an HTTP request, however, I don't know what is failing :(

Any help is appreciated...

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

#define BUFLEN 1024
#define PORT 8080

/*
 * Server.c
 *
 * Accept connections from a client
 *
 */

int main() {
    /* Useful Declarations */
    int fd, backlog, connfd;
    char buf[BUFLEN];
    struct sockaddr_in addr, cliaddr;
    socklen_t cliaddrlen;
    ssize_t rcount, i;

    /* IPv4 Declarations */
    addr.sin_addr.s_addr    = INADDR_ANY;
    addr.sin_family         = AF_INET;
    addr.sin_port           = htons(PORT);

    /* Create socket or return error */
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fputs("Unable to create a socket\n", stderr);
        return -1;
    }

    /* Bind socket to port or return error */
    if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
        fputs("Unable to bind socket to port\n", stderr);
        return -1;
    }

    backlog = 1;

    /* Start listening to port or return error */
    if (listen(fd, backlog) == -1) {
        fputs("Unable to listen to port\n", stderr);
        close(fd);
        return -1;
    }

    cliaddrlen = sizeof(cliaddr);

    /* Await for connection, or return error */
    if ((connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen)) == -1) {
        fputs("Unable to accept connection\n", stderr);
        close(fd);
        return -1;
    }

    /* Read up to 1500 bytes from socket or error*/
    if ((rcount = read(fd, buf, BUFLEN)) == -1) {
        fputs("Error occurred while reading from socket\n", stderr);
        printf("Error Number: %d\n", errno);

        for (i = 0; i < BUFLEN; i++)
            printf("%c", buf[i]);

        return -1;
    }

    close(fd);
    fputs("Socket closed\n", stdout);
    return 0;
}

I am aware that this will only print when the connection is closed by the client prematurely, but I can cross that bridge later when I come to it :)

  • 3
    Looks like code prints the buffer only when an error occurs. At that time, `buf` contents are not meaningful, so why print the buffer? – chux - Reinstate Monica Feb 18 '14 at 17:39
  • first of all, you can not create long pooling tcp connection in this way. it will just receive a packet from browser and connection will be closed. you have to implement bosh or websocket connection in your c program. – java seeker Feb 18 '14 at 17:40
  • "Read up to 1500 bytes ...", but `BUFLEN` is 1024. – chux - Reinstate Monica Feb 18 '14 at 17:42
  • @chux Yeah, it was originally set to 1500 bytes until I brought it back to 1024 and forgot to update the comment.In what sense are the buffer contents not meaningful? Surely any data received would still be in there, and I'd at least be able to get the start of the request? –  Feb 18 '14 at 17:44
  • 2
    They aren't meaningful because if the read returns an error it wouldn't have put anything in the buffer so you are just printing whatever garbage is there from an uninitialized buffer or (at best if you were in a loop) some mish-mash of data from previous reads. – Duck Feb 18 '14 at 18:07
  • @donaldacmartin _Maybe_ some data would be there, but it could be 0 bytes, 1 bytes, 2 bytes, etc. The rest would be simple whatever was there before the `read()`. I suspect `read()` does not specify the state of the buffer contents when -1 is returned. Code could initialize the buffer beofre the `read()` with `memset(buf, 0x55, sizeof buf)` and this _may_ provide insight. But even with that, on an error, the buffer contents are likely not meaningful. – chux - Reinstate Monica Feb 18 '14 at 18:40
  • On receiving a return value of `-1`, look to what error occurred and its cause rather than the buffer contents. See http://stackoverflow.com/questions/3180126/how-to-use-read-to-read-data-until-the-end-of-the-file – chux - Reinstate Monica Feb 18 '14 at 18:44
  • @chux No. If there was an error there was no data transfer. If there was a data transfer there was no error. – user207421 Feb 18 '14 at 20:31
  • @EJP So if one is reading a serial interface 100 bytes at a time and a parity error occurs after 20 successful bytes, you are suggesting that `read()` will return 20 the first call (with 20 good bytes in buffer) and then next time -1 (garbage in buffer)? Or something else like -1 with definitely not the 20 bytes in the buffer? Suppose either of our contentions would benefit with a citation. Have yet to find one that authoritatively describes the `buf` state when an error is returned. My view was based on experience with serial interfaces. – chux - Reinstate Monica Feb 18 '14 at 21:04
  • @EJP [read](http://linux.die.net/man/3/read) "If a read() is interrupted by a signal after it has successfully read some data, it shall return the number of bytes read." supports your point. – chux - Reinstate Monica Feb 18 '14 at 21:08
  • @chux If there is data in the socket receive buffer, it is transferred and the count returned. If there isn't, the read blocks until there is at least one byte. An error can only occur at this point. If it didn't work that way, TCP programs would constantly be losing data, and they don't. – user207421 Feb 18 '14 at 21:28

1 Answers1

1

Three things:

  • You should be using connfd, not fd to read from - fd is the original listening socket.
  • When printing out your buffer, use rcount to see how many bytes you got.
  • This also means that it only makes sense to print out your buffer if rcount > 0.
ldx
  • 3,984
  • 23
  • 28