1

So i need to recv an html file from the server to the client, the file is bigger than the buffer so i make several sends. Thats why i have this loop when i recv

while (i = recv(s, buf, TAM_BUFFER, 0)) {
            if (i == -1) {
                perror(argv[0]);
                fprintf(stderr, "%s: error reading result\n", argv[0]);
                exit(1);
            }
            while (i < TAM_BUFFER) {
                j = recv(s, &buf[i], TAM_BUFFER - i, 0);
                if (j == -1) {
                    perror(argv[0]);
                    fprintf(stderr, "%s: error reading result\n", argv[0]);
                    exit(1);
                }
                i += j;
            }
            /* Print out the file line by line. */
            printf("%s", buf);
}

the send looks something like this:

while (fgets(buf, sizeof(buf), fp)){
                    if (send(s, buf, TAM_BUFFER, 0) != TAM_BUFFER) errout(hostname);
                }

The problem is the loop never ends, becase it doesnt recv the eof and i is never 0, its just remain blocked there. I cant do the close to send the eof because after he recv the whole file, the client will ask for another file.

I tryed to send a SIGALRM if the loop stays blocked for longer than 5 seconds but it doesnt work as expected, because the loop wont stop, and it will throw an error.

Also how can i do to be able to recv less than TAM_BUFFER?(in the send, change the TAM_BUFFER -> strlen(buf)) I know i need to change the interior loop, but then ill have the same problem, j will not be 0 never, so i dont know how could i end it.(or maybe i dont need the second loop in this case).

EDIT: i cant send the lenght of the file beucause of the protocol im following

  • You need to send the length of the file ahead of the file, and only read exactly that many bytes from the socket when receiving the file. – user207421 Dec 17 '16 at 11:23
  • i forgot to add that, i already searched in stackoverflow and i found that option, but the protocol im following dont let me use that option. I need to send only what the clients asks, and i cant send the lenght. –  Dec 17 '16 at 11:27
  • 2
    You will have to change the protocol you're following if it doesn't support what you're trying to do. – user207421 Dec 17 '16 at 11:31
  • "*it doesnt recv the eof*" which eof? – alk Dec 17 '16 at 11:47
  • 1
    "*the protocol im following*" does not seem to be sufficiently specified for your kind of implementation then. You need to extent it. – alk Dec 17 '16 at 11:49

2 Answers2

2

TCP is a protocol used to transport a single unstructured octet stream in each direction. Shutdown of the connection (i.e. EOF) is the only way in TCP to signal to the peer that no more data will be sent in this connection. If you need a different way because you need to distinguish between multiple messages inside the same TCP connection then you need to use an application level protocol which can specify such message boundaries. This is usually done by fixed message size, prefixing the message with a length or by special boundary markers.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
-2

If you can't embed payload size in your protocol, you have to identify EOF by closing socket or checking for timeout. You can use select function and set timeout for it, see here Using select and recv to obtain a file from a web server through a socket and https://stackoverflow.com/a/30395738/4490542

Community
  • 1
  • 1
e.jahandar
  • 1,715
  • 12
  • 30
  • 1
    Checking for timeout is not an acceptable way to detect the end of a message. The timeout could happen for any reason whatsoever. – user207421 Dec 17 '16 at 11:50
  • A timeout is much to vague. Closing the socket might do, yes. – alk Dec 17 '16 at 11:51
  • @EJP suddenly, much of the implementations are using time out or closing socket right now, there isn't any portable solution without changing protocol. – e.jahandar Dec 17 '16 at 11:52
  • Implementations using timeout cannot possibly work, whether 'suddenly' or otherwise. There is no accounting for other people's incompetence, but what is your source for this assertion? Citation? Reference? Your last sentence agrees with my comment, although what 'portable' has to do with it is another mystery. – user207421 Dec 17 '16 at 11:57
  • i dont know who voted you -1 but if i cant change the protocol or close the socket, a timeout is the only way to go i think. –  Dec 17 '16 at 12:04