Click to See Complete Forum and Search --> : Check if FTP server isn't offline, my prog allways saying it is online


Owyn
May 19th, 2009, 08:00 AM
ftp::ftp() {
Connected = 0;
hListenSocket = INVALID_SOCKET;
hControlSocket = INVALID_SOCKET;
hDataSocket = INVALID_SOCKET;
bSendPort = 1;
ReadCommand = 0;
bMode=ASCII;

InitWinsock();

};

ftp::~ftp() {

};


void ftp::DoOpen( char *command)
{
char *szHost=NULL; /* remote host */

/*
* do not do anything if we are already connected.
*/
if( Connected ) {
//printf("Already connected. Close connection first.\n");
fflush(stdout);
return;
}

/*
* extract the remote host from command line (if given ).
* make a copy of the host name with strdup.
*/
if(!strcmp(command,"open") || !strcmp(command,"o")) {

//printf("Host:"); fgets(szBuffer,1024,stdin);
(void)strtok(szBuffer,"\n");
szHost = (char *)strdup(szBuffer);;
}
else if( !strncmp(command,"open ",5))
szHost = strdup(&command[5]);
else if( !strncmp(command,"o ",2) )
szHost = strdup(&command[2]);
else
szHost = strdup(command);


//printf("Connecting to %s\n",szHost);
hControlSocket = ConnectToServer(szHost,"21");

#if (defined(WIN32) || defined(_WIN32) )
Sleep(1);
#else
sleep(1);
#endif

if( hControlSocket > 0) {
//printf("Connected to %s\n",szHost);
/*#if (defined(WIN32) || defined(_WIN32) )

sprintf(command,"dftp: Connected to %s ", szHost);

SetConsoleTitle(command); // set console window title
#endif*/

Connected = 1; /* we ar now connected */
CNC=true;
GetReply(); /* get reply (welcome message) from server */
//DoLogin((char *)NULL); /* prompt for username and password */
//DoBinary(); /* default binary mode */
}
free(szHost); /* free the strdupped string */
}


int ftp::ConnectToServer(char *name, char *port)



{

int s;
unsigned int portnum;



struct sockaddr_in server;

struct hostent *hp;



while( name && *name == ' ') name++;

if( !name || ! (*name) )

return INVALID_SOCKET;



portnum = atoi(port);

bzero((char *) &server, sizeof(server));



if( isdigit(name[0])) {

server.sin_family = AF_INET;

server.sin_addr.s_addr = inet_addr(name);

server.sin_port = htons(portnum);

}

else{

if ( (hp = gethostbyname(name)) == NULL)

{
#if (!defined( _WIN32 ) || !defined( WIN32 ))

perror("gethostbyname");
#else
//printf("gethostbyname: error code: %d\r\n", WSAGetLastError());

#endif
return INVALID_SOCKET;

}

bcopy(hp->h_addr,(char *) &server.sin_addr,hp->h_length);

server.sin_family = hp->h_addrtype;

server.sin_port = htons(portnum);

}/* else */



/* create socket */

if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 1) {
#if (!defined( _WIN32 ) || !defined( WIN32 ))
perror("socket");
#else
//printf("socket: error code: %d\r\n", WSAGetLastError());
#endif

return INVALID_SOCKET;

}



if (connect(s,(struct sockaddr *)&server, sizeof(server))< 0) {

#if (!defined( _WIN32 ) || !defined( WIN32 ))
perror("connect");
#else
//printf("connect: error code: %d\r\n", WSAGetLastError());
#endif


return INVALID_SOCKET;

}



setsockopt(s,SOL_SOCKET,SO_LINGER,0,0);

setsockopt(s,SOL_SOCKET,SO_REUSEADDR,0,0);

setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,0,0);

hDataSocket = s;



return s;

}

when i do DoOpen() it shows allways Connected == 1, and CNC == true ... where is the mistake?

Richard.J
May 19th, 2009, 08:34 AM
how is INVALID_SOCKET defined? Your ConnectToServer() method returns it on errors, but you check if the result is >0.

Owyn
May 19th, 2009, 08:54 AM
i changed all return INVALID_SOCKET; to return NULL; but nothing changed

Richard.J
May 19th, 2009, 10:06 AM
then run through the code with the debugger and see where it fails. Should be fairly easy.

Owyn
May 19th, 2009, 10:35 AM
setsockopt(s,SOL_SOCKET,SO_LINGER,0,0);

setsockopt(s,SOL_SOCKET,SO_REUSEADDR,0,0);

setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,0,0);

hDataSocket = s;



return s;

this part of code is wrong, s is a random number not depending if connection successefull or not =\ i think i need a new way to detect if FTP online or offline, any suggestions?

Richard.J
May 19th, 2009, 11:03 AM
the setsockopt part cannot be wrong, the failure must be before. s can be anything, so don't assume it has to have a specific value.
socket() returns -1 on failure, so you should check for that (also I admit that 0 does not look like a valid socket ;-)).
IMO, trying to connect() to your server is the only chance to see if it is up (or at least if you can reach it from your network).

Try to create a minimum example that compiles and reproduces the failure, and we can check. The code fragments you posted are not enough.

HTH,
Richard

Owyn
May 19th, 2009, 11:19 AM
after hDataSocket = s; i did a display "%d",hDataSocket, if server was up it was 1960, 1900, 1768, if server was offline it was 1940 or 1876 or some other, 0isn't a valid socket but check is checking if value more than 0, 0 is not so it should be set to offline status if we got 0, i'm writing a dynamic library, not a win32 program, so posting something full may be a problem.
and i thought that code has if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 1) { check with return NULL; if condition is met, but it's not ... maybe you could post a few lines of code to check ftp server status with socket() ?

Richard.J
May 19th, 2009, 11:30 AM
as I said, s can be any value. It is just the socket on your client side, it has nothing to do with the availability of your server. The values you name all look like valid sockets to me, so where's the problem? Are you sure your server is down on some attempts?
If connect() succeeds that means a connection has been established.

Hey, and unless you do not post a fully compilable and running code, I won't either ;-)

No offense,
Richard

Owyn
May 19th, 2009, 11:39 AM
i'm sure server is offline, i turn it off before i check it)
may that server and client of ftp is the same machine be the problem btw? O_o or that there are other network services running?

..

Owyn
May 19th, 2009, 12:57 PM
now i think it does matter, i tried to connect to non valid address and instead of giveing me back random number for 's' it just froze the application, but that's not a variant also =\

Richard.J
May 19th, 2009, 01:56 PM
you need to understand the nature of a socket. You create it locally in the first step, that gives you your local socket. The value might be within an area of 19something, as you already saw.

Then you try to connect() to a remote address. If your PC can resolve the remote address, a connection attempt is made. If there is someone at the remote address (listening on the port you specify), then the attempt will succeed and connect() will return without an error. Otherwise, you'll encounter an error.

If you are doing your test with client and server on the same machine, maybe you are mixing up with a service already running on it? Try using your client with a port other than 21, use an arbitrary port.
Or checkout http://technet.microsoft.com/en-us/sysinternals/bb897437.aspx for TcpView, a great tool.

I didn't check your code yet, will do later.

OTK,
Richard

Owyn
May 19th, 2009, 02:16 PM
i tried to connect to port 22 not 21 into my FTP (on my machine) and it returned NULL and didn't freeze

then i tried to connect to port 21 with FTP server turned off and it returned 1872 socket

then i made FTP server listen on 22 port and tried to connect to it while it is offline, got NULL

wonder what responds on 21 port if not my FTP ? =\ *(oh looks like my proxy server, thx for that program)

now problem is application freezes if can't access IP ( i tried non existing IP to connect, think my IP will act the same if i go offline)

Richard.J
May 19th, 2009, 02:31 PM
you'll have to wait long enough, DNS resolution may take minutes ...
But you are on the right track ;-)

Owyn
May 19th, 2009, 03:41 PM
i don't want minutes =\ and me and anyone else will think program just not responding, is it possible to limit resolution time or something?

Owyn
May 20th, 2009, 07:12 AM
i thought problem might be in gethostbyname.... but i have if( isdigit(name[0])) {

server.sin_family = AF_INET;

server.sin_addr.s_addr = inet_addr(name);

server.sin_port = htons(portnum);

} check =\

Richard.J
May 20th, 2009, 10:15 AM
to limit the time for the connect() request to succeed, you can
- set your socket to non-blocking
- call connect which will now immediately return with an error indicating the function would block
- call select with the desired timeout
- if select returns, either your connection succeeded or the timeout happened.

As to gethostbyname: it may fail if you pass a name (not IP address) to it which your operating system can not resolve.

Owyn
May 20th, 2009, 12:22 PM
- call connect which will now immediately return with an error indicating the function would block
what do you mean? i do call connect
if (connect(s,(struct sockaddr *)&server, sizeof(server))< 0) {

return NULL;

}

Richard.J
May 20th, 2009, 12:35 PM
all of those 4 items I mentioned do belong together in this order. Follow them from top to bottom and you will be able to restrict the connection attempt to match your timeout requirements.
But one addtional thing: if the attempt times out, make sure to close the socket or you might have an unwanted connection later.

Owyn
May 20th, 2009, 12:48 PM
ok... i got timeout thing working with select, but when i wrote correct ip back and turned on my FTP nothing changed =\ i still get my timeout and no connection


timeval tvTimeout;
tvTimeout.tv_sec = 4; // <-- Maximum (?) timeout value
tvTimeout.tv_usec = 0;

fd_set fds; FD_ZERO(&fds);

FD_SET(s, &fds);

INT iStatus = SOCKET_ERROR;

iStatus = ::select(0, &fds, NULL, NULL, &tvTimeout);
if (SOCKET_ERROR == iStatus || 0 == iStatus) {
return NULL;
}

Richard.J
May 20th, 2009, 04:29 PM
last chance to post a complete sample code that demonstrates your problem ...