Problems with file descriptor

Hi,
look at the following code:
The client after estabilishing a connection with the server does the following:
if ((peter = fopen(argv[1], "r")) == NULL){
printf("errore\n");
exit(0);
}

send_file\(peter, sockfd\); /* transfers the file to the server */
fclose\(peter\);
printf\("File spedito\\n"\);

read\(sockfd, \(char *\) &res, sizeof\(res\)\);  /* here it waits for a receipt */
res = ntohs\(res\);
if\(res == RECEIPT\)
  printf\("RECEIPT received\\n"\);
else
  printf\("RECEIPT not received\\n"\);
                                                                            
close\(sockfd\); 

}

The server after accepting the connection does the following:
if ((fp = fopen("transazione", "w")) == NULL){
printf("errore\n");
exit(0);
}
get_file(fp, connfd); /* obtain the file from the client */
fclose(fp);
printf("File received\n");

    shutdown\(connfd, SHUT_RD\);
    res = htons\(RECEIPT\);
    writen\(connfd, \(char *\) &res, sizeof\(res\)\);
    printf\("RECEIPT sent\\n"\);

}
The whole program compile but when I try to execute it the client acrtually send the file and blocks on the read call on the socket and the server bloks on the get file function, never returning? Anyone can help?
By the way the two function get_file and send_file read from the socket and write to the file(get_file) or the opposite(read from the file e write to the socket, send_file)
Thanx in advance!!!
Matteo

Matteo,

It would help if you posted the code for the getfile function.

Cheers!

Sorry...
here it goes the getfile and sendfile function:

void
get_file(FILE *fp, int sockfd){
int n;
char buf[MAXSIZE];

/* read from the socket until i receive EOF */
while ((n = recv(sockfd, buf, MAXSIZE, MSG_WAITALL)) > 0){
if (fwrite(buf, sizeof(char), n, fp) != n){
printf("error\n");
exit(0);
}
}
return;
}

void
send_file(FILE *fp, int sockfd){
int n;
char buf[MAXSIZE];

/* write the file on socket */
while ((n = fread(buf, sizeof(char), MAXSIZE, fp)) > 0){
if (writen(sockfd, buf, n) != n){
printf("socket error\n");
exit(0);
}
}
return;
}

MSG_WAITALL is a new one on me. Looking it up with google I see: "If your system supports MSG_WAITALL, recv() will not return until required length of data is recieved entirely". I didn't see where MAXSIZE is defined, so let's say it is 1024. It sounds to me like recv must block until it gets 1024 bytes. But what if the file is 1025 bytes? The first recv would work. But the second recv would get the final byte and wait forever for 1023 more bytes.

But again, I have no experience with this MSG_WAITALL flag, so I'm not sure if this analysis is correct. Easy to test though... Try sending a file that is a multiple of MAXSIZE in length.

MSG_WAITALL beaves exactly as you said, wait for the exact amount of data you have requested, but can return fewer data if an error occur, a signal is caught, or for connection shutdown. In the latter case it returns 0, but beaves the same(return 0) also when an EOF is reached. In my case when the EOF is reached(that means the sender file's is finished) recv returns 0 and break the loop.
It would work properly if i didn't use the code that follow getfile sendfile in client and server code, but I don't know why when I try to send again data after the getfile call the client blocks!
Hope someone can help me.
Thanx for the attention!
Ciao

Why would the socket see an EOF? You do a bunch of writen() calls. I don't know what writen is. Does it somehow know when the last writen occurred and do a half close on the socket?

Don't mind about writen you can get rid of it and replace with write, it will work fine. When read from the file and gets EOF the send_file function send it through the socket to get_file and recv return 0 as if it were interrupted or shutdown the connection. It is a normal beavior I think...
Comments?
Ciao
Matteo

It does not work that way. You can not write an EOF to a socket any more that you can write EOF to a file. EOF is not a character. You need to close() or shutdown() the socket. Only then will the other side see an EOF condition.

I have a question. If doing a file transfer, shouldn't there be acks sent back to the source, so that the source can send the next datablock?

I think that a sequence like this would work:

file dest:send ack. file src: wait for ack.
file src: get ack. send data. file dest: wait for data
file dest: get data. send ack. ..... so on.

if at any point, if the file src doesn't get ack, it can resend the data, and we could use normal read and write on the sockets.

FWIW - some OSes have an actual EOF character. DOS uses ascii 26 for EOF for "text" files, for example.

I think that's where the idea of an EOF character came from.

Yes I made a mistake, It doesn't send EOF at all, sorry for my bad english!
But as a matter of fact if you build a client and a server only with those two function(send_file and get file) it works, try to do so.
I took the example from "The C programming language" book. Actually the example was copying between 2 files or from stdin to a file(I can't remember now...), but since a socket is threated like a low level I/O descriptor(that with function similar to system call not FILE *) if you replace the descriptor with the socket it should work the same. I tried and it worked so, why? What's wrong with my reasoning?
Any comment?
Thanx everybody.
Ciao

The fact is that when you run the 2 function alone, the send_file function finishes while the get_file function waits. When send_file finishes immediatly halt the program so closing sockets! That's why get_file function finishes as well, because it sees the socket's closure .
Sorry for the banal question!
And thanx for all answers.
Ciao
Matteo