im trying to build FTP server of mine. the server already knows to send files (to clients) but the problem is about the uploads (from clients)...
CODE
CLIENTS RAWS ARE:
[L] TYPE I [L] 200 Type set to I [L] PORT 127,0,0,1,13,121 [L] 200 Port command successful. [L] STOR tst.tst
then the server connects to the 3449 port. (13*256)+121 then it sending "150 Opening BINARY mode data connection for tst.tst." to the client. and the client starts to send the file....... but the problem is that my server doesnt know when the client finished uploading the file.
is there any escape character or something? any raw command? or maybe something i missunderstood in the very begining of the FTP protocol?
hmm 10x alot but didnt find something usefull there
maybe someone knows the answer to my question?
belgther
May 27 2005, 04:18 AM
As far as I know, the file size is sent before uploading by the client, so that the space is occupied. After that, the client starts to upload the file, and after the number of transferred bytes are same as the filesize, then the upload is finished.
saetji
May 27 2005, 06:08 AM
I don't think filesize is sent before hand because I was reading here in another thread that you can append to a file starting at the 50gb position because the filesize wasn;t sent beforehand
Candypapa
May 27 2005, 11:11 AM
thats right, the client sends the SIZE command only when it wants to know if the file exists on the server and to know where from to resume this file then the server sends the size.
and i would like to metion that the client doesnt closes the socket after the transfer is over so i cant determine the finish by socket state.
anyway, the client doesnt sends the size to the server... so it must be an escape character or something else. ive tried to sniff it but didnt found it so it must be something else.
so i still need a help..
Dubby
May 27 2005, 01:51 PM
well i really don't know much (= anything) about FTP protocol, but i scrolled through FTP-Protocol (RFC959, here: http://www.ietf.org/rfc/rfc959.txt ) and i think what you mean/need might be found under 3.1.1.4 "IMAGE TYPE (as you used TYPE I for this transfer) and/or 3.4 "Transfer Modes".
e.g. from 3.4.1 STREAM MODE:
QUOTE
In a record structured file EOR and EOF will each be indicated by a two-byte control code. The first byte of the control code will be all ones, the escape character. The second byte will have the low order bit on and zeros elsewhere for EOR and the second low order bit on for EOF; that is, the byte will have value 1 for EOR and value 2 for EOF. EOR and EOF may be indicated together on the last byte transmitted by turning both low order bits on (i.e., the value 3) .....
please forgive me if his quote is totally displaced, as i said i don't really know much about FTP protocol maybe you already read those, if so, ignore this post
Candypapa
May 28 2005, 11:42 AM
tried it, and it didnt helped me any other sugestion?
Killaloop
May 28 2005, 07:58 PM
the ftp client sends data until it reaches the eof. then it still looks like data is beeing send, but actually the client only waits for the ftp server to tell him he got all the data. so the client waits that the server closes the socket and sends 226 Tranfer complete back. so basically all what you need is checking the status of the socket, if its still alive.
CODE
#define STDSOCKTIMEOUT 5 int CheckStatus(SOCKET sd, int nsec, int nmsec /*=0*/) { int retval = 0;
fd_set sdset; struct timeval tv;
if (nsec == 0 && nmsec == 0) return(1);
FD_ZERO(&sdset); //initialize the sdset structure FD_SET(sd,&sdset); //set the structure tv.tv_sec = nsec; //set server to wait for nsec seconds tv.tv_usec = nmsec * 1000;
retval = select(sd+1,&sdset,NULL,NULL,&tv);
return(retval); }
if (CheckStatus(datasocket,10*STDSOCKTIMEOUT,0) <= 0) { //check if data is beeing send Close(datasocket);
I might be wrong, but as far as I know, most FTP clients create FTP-Data connections with establishing FTP connections, and close them after they terminate FTP connections... That's what I know, but I might be wrong.
Candypapa
May 29 2005, 03:37 AM
its kind of stupidly to measure each second if data is still being send, anyway thats works!!! now another problem i have.
there is a little difference betwen the Source file and the Destination file after it being sent.
The Source file contains the string "test" and it lenghs 4bytes. The Destinatiof file contains the string "test" & 00 & 0A and it lenghs 6bytes.
why is that? tried to sniff the socket for the 00 & 0A and they werent there, and im my program i dont have any code that adds the 00 & 0A.
so why is that?
Killaloop
May 29 2005, 07:03 AM
do you use binary mode or ascii mode? for ascii mode an ascii file will always contain \r\n at the end not only \n and we need to rip this off.
CODE
#define MAXPACKETSIZE 4096 //max size of a sending packet (4KB)
int RecvN(SOCKET sd, char *ptr, int nbytes) { int nleft, nread;
if (sd == SOCK_INVALID || ptr == NULL || nbytes == 0) return(-1); *ptr = '\0'; //initialize to an empty string
long RecvFileData(int fdw) { char *packet, *tmppacket; int packetlen = 0, tmppacketlen = 0; char lastchar = ' '; do { if (CheckStatus(datasocket,10*STDSOCKTIMEOUT,0) <= 0) { free(packet); return(0); //if the data stops being sent } packetlen = RecvN(datasocket,buffer,MAXPACKETSIZE); tmppacket = BtoA(lastchar,packet,packetlen,&tmppacketlen); lastchar = tmppacket[tmppacketlen-1]; write(fdw,tmppacket,tmppacketlen); free(tmppacket); nbytes += packetlen; }while(packetlen == MAXPACKETSIZE);
free(packet); return(nbytes); }
int main() { int fdw,oflag; long nbytes =0; packet = (char *)malloc(MAXPACKETSIZE); buffer = (char *)malloc(MAXPACKETSIZE); oflag |= O_BINARY; fdw = open(filepath,oflag,0666); //filepath should be real physical path for the file. nbytes = RecvFileData(fdw); Close(fdw); return 0; }
a little mess in this code, but you should get the idea. and no belgther, the client does not close anything on his own. thats the reason why we look every few seconds if the socket is still alive. so its a good and the only right idea candypapa.
Erion
May 30 2005, 12:04 PM
well, I coded my own FTP server some time a go, and what I did was jut read fromt he socket untill nothing is else is received (guess that is similar to what you are doing)
CODE
#define FILE_START_BANNER "150 File status okay; about to open data connection.\r\n"
ClientConnection just creates and connects to the specified IP:port RecvTimeout is like recv but has a max timeout specified (in milliseconds)
Killaloop
Jun 2 2005, 04:00 AM
well erion this will screw up your file if you transfer in ascii mode because windows uses \r\n unlike to *nix systems that use \n only. if you transfer in ascii mode on windows you have to strip away the end like my code shows, else your file is 2 bytes bigger like candypapa's problem shows.
Erion
Jun 3 2005, 10:47 AM
QUOTE(Killaloop @ Jun 2 2005, 04:00 AM)
well erion this will screw up your file if you transfer in ascii mode because windows uses \r\n unlike to *nix systems that use \n only. if you transfer in ascii mode on windows you have to strip away the end like my code shows, else your file is 2 bytes bigger like candypapa's problem shows.
yes your are right, on Windows the End of Line is a \r\n (0x0d 0x0a) whilst in *nix it is just \n.
I've always gotten a little bit confused about that ASCII and BINARY modes. Binary mode sends the file 'as is' but what does ASCII mode exactly do?
What I do on my code is open the file in binary or text depending on the request and then transfer the read data, I thought that the problem should be solved that way, but maybe I am wrong.
belgther
Jun 4 2005, 03:02 AM
How about strings in C codes? Because it's usually used that strings contain "\r\n" when using the printf() function. Will it not cause a transfer problem in ASCII mode?
Killaloop
Jun 4 2005, 05:20 AM
in binary mode data is transfered bit by bit and in ascii mode the file should get changed so the EOL characters match for the target os. if you transfer a text based file from unix to windows (or other direction) you should use ascii mode and the server should be able to convert the EOL characters to match the OS. many don't do it and thats the reason why I use wordpad as standard editor, it can handle both eol characters and won't have everything in one row. problem is only with compressed data (zip or whatever) you should transfer the readme out of the zip to make it nice readable for everyone. I'm not sure your way handles the eol characters right, but if it really cares you, you can easy test it. anyhow I'm a perfectionist, others may not care about this stuff
Erion
Jun 6 2005, 04:09 AM
well, b4 replying the other day I played a little with it, transferring files in binary and ASCII from wins to Unix and vice versa.... files displayed ok, and the quantity of transferred bytes was different in both methods, so looked like in binary mode the eol was considered as 2 bytes while in ASCCI it was just one.
If I ever have some spare time I'll do some more testing, I like to have things well coded too
Thx for your replies and suggestions m8
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.