Help with FTP - TCP-IP

This is a discussion on Help with FTP - TCP-IP ; I'm a student experimenting with the FTP protocol and learning C++. I've been able to connect and send an initial command "USER xxxxxx \n" to which I receive a 331 reply asking for a password. From here I'm lost as ...

+ Reply to Thread
Results 1 to 15 of 15

Thread: Help with FTP

  1. Help with FTP

    I'm a student experimenting with the FTP protocol and learning C++.
    I've been able to connect and send an initial command "USER xxxxxx \n"
    to which I receive a 331 reply asking for a password. From here I'm
    lost as I am unable to successfully send the password. I've tried
    "PASS xxxxxx \n" to which I always receive the error "500 ?". What's
    interesting to me is that even without logging in I can send one
    command (such as STAT) successfully but regardless what I send second
    I always receive the "500 ?" error.

    Any ideas what I could be doing wrong? Here's my code, and as a
    beginner I'm sure it's ugly:


    #include // Lines beginning with # are directives for the
    preprocessor - compiler - to include a file
    #include
    #include
    #include
    #include
    #include
    #include

    using namespace std; // We will be using the standard C++ library

    // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib

    int ftpSend (char c[], SOCKET s, int i)
    {
    int x = send(s, c, i,0);
    if (x > 0)
    {
    printf("\nSend successfully sent %d bytes\n", x);
    }
    else
    {
    printf("Send failed\n%d\n", WSAGetLastError());
    }
    return x;
    };

    main()
    {
    WSADATA ws;
    WSAStartup(0x0101, &ws); // specifies Winsock version

    SOCKET listener;
    SOCKADDR_IN sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");
    sin.sin_port = htons(27015);

    int tcp_socket; // will be the socket
    struct sockaddr_in peer; // name of the host to connet to
    char recvbuffer[1024]; // used to store received data
    char buffer2[1024];

    peer.sin_family = AF_INET; // Internet - TCP/IP
    peer.sin_port = htons(21); // Port on host to connect to
    peer.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx"); // Host's
    ip address in network byte order

    listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener == INVALID_SOCKET)
    {
    printf("Listener socket failed\n");
    }
    int x = bind(listener, (struct sockaddr*) &sin, sizeof(sin));
    if (x == 0)
    {
    printf("Bind successful\n");
    }
    else
    {
    printf("Bind failed\n%d\n", x);
    }

    x = listen(listener, 5);
    if (x == 0)
    {
    printf("Listener activated\n");
    }
    else
    {
    printf("Listener failed\n");
    }

    tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
    x = connect(tcp_socket, (struct sockaddr*)&peer, sizeof(peer));
    if (x == 0)
    {
    printf("Connect successful\n");
    }
    else
    {
    printf("Connect failed\n");
    }

    x = recv(tcp_socket, recvbuffer, sizeof(recvbuffer),0);
    if (x > 0)
    {
    printf("Received %d bytes\n", x);
    for (int y = 0; y < x; y++)
    {
    cout << (char)recvbuffer[y];
    }

    for (int y = 0; y < x; y++)
    printf("%d ", recvbuffer[y]);
    }
    else
    {
    printf("Send failed\n%d\n", WSAGetLastError());
    if (x == 0)
    {
    printf("Connection closed\n");
    }
    }
    char ccc[] = "USER xxxxxx \n";
    ftpSend(ccc, tcp_socket, sizeof(ccc));

    x = recv(tcp_socket, recvbuffer, sizeof(recvbuffer),0);
    if (x > 0)
    {
    printf("Received %d bytes\n", x);
    for (int y = 0; y < x; y++)
    {
    cout << (char)recvbuffer[y];
    }
    }
    else
    {
    printf("Receive failed\n%d\n", WSAGetLastError());
    }

    char ccp[] = "PASS xxxxxx \n";
    ftpSend(ccp, tcp_socket, sizeof(ccp));

    x = recv(tcp_socket, recvbuffer, sizeof(recvbuffer),0);
    if (x > 0)
    {
    printf("Received- %d bytes\n", x);
    for (int y = 0; y < x; y++)
    {
    cout << (char)recvbuffer[y];
    }
    }
    else
    {
    printf("Receive failed\n%d\n", WSAGetLastError());
    }

    WSACleanup();

    system("PAUSE");
    }


  2. Re: Help with FTP

    In article ,
    Bryan B wrote:
    >I'm a student experimenting with the FTP protocol and learning C++.
    >I've been able to connect and send an initial command "USER xxxxxx \n"
    >to which I receive a 331 reply asking for a password. From here I'm
    >lost as I am unable to successfully send the password. I've tried
    >"PASS xxxxxx \n" to which I always receive the error "500 ?".


    The FTP protocol (along with SMTP) requires \r\n not just \n
    RFC 959 section 5.3

  3. Re: Help with FTP

    On Wed, 28 May 2008 10:59:59 -0700, Bryan B wrote:

    > Any ideas what I could be doing wrong? Here's my code, and as a beginner
    > I'm sure it's ugly:


    Two things that spring out:

    > int ftpSend (char c[], SOCKET s, int i) {


    Does copying SOCKETs work? I'm not sure.

    > int x = send(s, c, i,0);
    > if (x > 0)
    > {
    > printf("\nSend successfully sent %d bytes\n", x);
    > }
    > else
    > {
    > printf("Send failed\n%d\n", WSAGetLastError());
    > }
    > return x;
    > };


    What happens when x < i?

    HTH,
    M4

  4. Re: Help with FTP

    Bryan B writes:


    [...]

    > Any ideas what I could be doing wrong? Here's my code, and as a


    [...]

    > int ftpSend (char c[], SOCKET s, int i)
    > {
    > int x = send(s, c, i,0);
    > if (x > 0)
    > {
    > printf("\nSend successfully sent %d bytes\n", x);
    > }
    > else
    > {
    > printf("Send failed\n%d\n", WSAGetLastError());
    > }
    > return x;


    send is not guaranteed to send all bytes in one go. You'll need to
    check the number of bytes it actually sent, and if it wasn't all of
    the bytes you wanted sent, you'll have to keep calling it.

    [...]

    > x = recv(tcp_socket, recvbuffer, sizeof(recvbuffer),0);
    > if (x > 0)
    > {
    > printf("Received %d bytes\n", x);
    > for (int y = 0; y < x; y++)
    > {
    > cout << (char)recvbuffer[y];
    > }
    >
    > for (int y = 0; y < x; y++)
    > printf("%d ", recvbuffer[y]);
    > }
    > else
    > {
    > printf("Send failed\n%d\n", WSAGetLastError());
    > if (x == 0)
    > {
    > printf("Connection closed\n");
    > }
    > }


    As with send, recv will only return what's available, which may not be
    the entire command. FTP is line-oriented, so you should keep calling
    recv until you see "\r\n".

    > char ccc[] = "USER xxxxxx \n";


    The space there after the username is unusual.

    [...]

    > char ccp[] = "PASS xxxxxx \n";


    There, too. If it's really in your code, it could well be why it
    always says the password is wrong.

    Good luck!

    ----Scott.

  5. Re: Help with FTP

    On May 28, 3:01*pm, Martijn Lievaart wrote:
    > Two things that spring out:
    >
    > > int ftpSend (char c[], SOCKET s, int i) {

    >
    > Does copying SOCKETs work? I'm not sure.



    In Windows, SOCKETS are opaque handles, and only their value is
    meaningful. So yes, they can be copied at whim.

  6. Re: Help with FTP

    On May 28, 3:01*pm, Rick Jones wrote:

    > send() against a non-blocking socket is not guaranteed to send all the
    > bytes. *against a blocking socket it is supposed to return only after
    > error or all the bytes are sent.


    If that were true, the common practice of calling 'alarm' and then a
    blocking 'write' would only work for fatal errors. Otherwise, how
    would you know how many bytes had been sent or received when the
    timeout occurred? For some types of errors, 'write' will actually
    return the number of bytes successfully sent (or queued for send)
    before the "error" happened. And not all errors are fatal to the
    connection.

    DS

  7. Re: Help with FTP

    On Thu, 29 May 2008 16:21:11 -0700, David Schwartz wrote:

    > On May 28, 3:01*pm, Rick Jones wrote:
    >
    >> send() against a non-blocking socket is not guaranteed to send all the
    >> bytes. *against a blocking socket it is supposed to return only after
    >> error or all the bytes are sent.

    >
    > If that were true, the common practice of calling 'alarm' and then a
    > blocking 'write' would only work for fatal errors. Otherwise, how would
    > you know how many bytes had been sent or received when the timeout
    > occurred? For some types of errors, 'write' will actually return the
    > number of bytes successfully sent (or queued for send) before the
    > "error" happened. And not all errors are fatal to the connection.


    If you read "error" above as "something exceptional", like an actual
    transmission error or an alarm going off, it makes sense. And indeed, not
    all errors are fatal to the connection, but who said so?

    M4

  8. Re: Help with FTP

    David Schwartz wrote:
    > On May 28, 3:01?pm, Rick Jones wrote:
    > > send() against a non-blocking socket is not guaranteed to send all
    > > the bytes. ?against a blocking socket it is supposed to return
    > > only after error or all the bytes are sent.


    > If that were true, the common practice of calling 'alarm' and then a
    > blocking 'write' would only work for fatal errors. Otherwise, how
    > would you know how many bytes had been sent or received when the
    > timeout occurred?


    True enough, and netperf even uses this.

    rick jones
    --
    portable adj, code that compiles under more than one compiler
    these opinions are mine, all mine; HP might not want them anyway...
    feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...

  9. Re: Help with FTP

    On May 29, 4:57*pm, Martijn Lievaart wrote:
    > On Thu, 29 May 2008 16:21:11 -0700, David Schwartz wrote:
    > > On May 28, 3:01*pm, Rick Jones wrote:


    > >> send() against a non-blocking socket is not guaranteed to send all the
    > >> bytes. *against a blocking socket it is supposed to return only after
    > >> error or all the bytes are sent.


    > > If that were true, the common practice of calling 'alarm' and then a
    > > blocking 'write' would only work for fatal errors. Otherwise, how would
    > > you know how many bytes had been sent or received when the timeout
    > > occurred? For some types of errors, 'write' will actually return the
    > > number of bytes successfully sent (or queued for send) before the
    > > "error" happened. And not all errors are fatal to the connection.


    > If you read "error" above as "something exceptional", like an actual
    > transmission error or an alarm going off, it makes sense. And indeed, not
    > all errors are fatal to the connection, but who said so?


    You get a contradiction either way:

    1) If "error" only means a fatal error: the statement is false. Non-
    fatal errors also cause 'write' or 'send' to terminate.

    2) If "Error means a non-fatal error: the statement is false. Non-
    fatal errors may cause 'write' to return fewer bytes than actually
    sent in a case where you need to know the number sent because the
    connection is not lost. So you have to correctly handle the case where
    the return value is less than the number of bytes sent even with a
    blocking socket.

    Scott Gifford was correct when he said:

    >>send is not guaranteed to send all bytes in one go. You'll need to
    >>check the number of bytes it actually sent, and if it wasn't all of
    >>the bytes you wanted sent, you'll have to keep calling it.


    The responses that argued that you don't need to were incorrect. They
    fail to account for the possibility of non-fatal errors after some,
    but not all, of the bytes have been sent.

    DS

  10. Re: Help with FTP

    On Fri, 30 May 2008 16:32:26 -0700, David Schwartz wrote:

    > On May 29, 4:57*pm, Martijn Lievaart wrote:
    >> On Thu, 29 May 2008 16:21:11 -0700, David Schwartz wrote:
    >> > On May 28, 3:01*pm, Rick Jones wrote:

    >
    >> >> send() against a non-blocking socket is not guaranteed to send all
    >> >> the bytes. *against a blocking socket it is supposed to return only
    >> >> after error or all the bytes are sent.

    >
    >> > If that were true, the common practice of calling 'alarm' and then a
    >> > blocking 'write' would only work for fatal errors. Otherwise, how
    >> > would you know how many bytes had been sent or received when the
    >> > timeout occurred? For some types of errors, 'write' will actually
    >> > return the number of bytes successfully sent (or queued for send)
    >> > before the "error" happened. And not all errors are fatal to the
    >> > connection.

    >
    >> If you read "error" above as "something exceptional", like an actual
    >> transmission error or an alarm going off, it makes sense. And indeed,
    >> not all errors are fatal to the connection, but who said so?

    >
    > You get a contradiction either way:


    (snip)

    > 2) If "Error means a non-fatal error: the statement is false. Non- fatal
    > errors may cause 'write' to return fewer bytes than actually sent in a
    > case where you need to know the number sent because the connection is
    > not lost. So you have to correctly handle the case where the return
    > value is less than the number of bytes sent even with a blocking socket.


    I still fail to see how that is different from the statement above. The
    send call returns when all bytes are send, or something exceptional
    occurs. Nowhere is said that this cannot result in a partial write.

    Or are there situations on a blocking socket where the send call can
    return a status of success and still have sent less than the requested
    amount of bytes? In that case you are correct.

    M4

  11. Re: Help with FTP

    On May 31, 2:19*am, Martijn Lievaart wrote:

    > I still fail to see how that is different from the statement above. The
    > send call returns when all bytes are send, or something exceptional
    > occurs. Nowhere is said that this cannot result in a partial write.


    Right here:

    (Scott Gifford)
    >>> send is not guaranteed to send all bytes in one go. You'll need to
    >>> check the number of bytes it actually sent, and if it wasn't all of
    >>> the bytes you wanted sent, you'll have to keep calling it.


    (Rick Jones, in reply)
    >>send() against a non-blocking socket is not guaranteed to send all the
    >>bytes. against a blocking socket it is supposed to return only after
    >>error or all the bytes are sent.


    This is incorrect. Because not all errors are fatal, an error can
    result in a partial write. So you do need to check the number of bytes
    sent. Scott Gifford is correct and Rick Jones is incorrect.

    Rick Jones would be correct if all errors were fatal, because it
    doesn't matter how many bytes were queued before a fatal error. So the
    return value would be useless. However, if there's a non-fatal error,
    you *do* need to know how many bytes were sent.

    DS

  12. Re: Help with FTP

    On Sat, 31 May 2008 02:56:09 -0700, David Schwartz wrote:

    > On May 31, 2:19*am, Martijn Lievaart wrote:
    >
    >> I still fail to see how that is different from the statement above. The
    >> send call returns when all bytes are send, or something exceptional
    >> occurs. Nowhere is said that this cannot result in a partial write.

    >
    > Right here:
    >
    > (Scott Gifford)
    >>>> send is not guaranteed to send all bytes in one go. You'll need to
    >>>> check the number of bytes it actually sent, and if it wasn't all of
    >>>> the bytes you wanted sent, you'll have to keep calling it.

    >
    > (Rick Jones, in reply)
    >>>send() against a non-blocking socket is not guaranteed to send all the
    >>>bytes. against a blocking socket it is supposed to return only after
    >>>error or all the bytes are sent.

    >
    > This is incorrect. Because not all errors are fatal, an error can result
    > in a partial write. So you do need to check the number of bytes sent.
    > Scott Gifford is correct and Rick Jones is incorrect.
    >
    > Rick Jones would be correct if all errors were fatal, because it doesn't
    > matter how many bytes were queued before a fatal error. So the return
    > value would be useless. However, if there's a non-fatal error, you *do*
    > need to know how many bytes were sent.


    I think we actually agree, but don't know it yet. :-)

    Also, I'm not keeping this thread alive to see who's "right" and who's
    not. I'm trying to see if I really don't understand it, or if I'm
    correct, but cannot put it in the correct words. In other words, I'm
    trying to learn something.

    Both are correct or incorrect, depending how you look at it. Scott said
    nothing about errors. His comment was about a non-blocking socket. It may
    also have been about E_INTR, but that is absolutely not clear. As this
    was about blocking sockets, Rick corrected that.

    However, Ricks statement is also confusing. Send may return in a blocking
    context with fewer bytes written than requested. However, this is always
    due to an exceptional situation, if you see E_ALARM and E_INTR as an
    exceptional situation. AFAIK, send does never return with a success
    status code if not all bytes are written. This is how I interpreted Ricks
    statement, and viewed that way, I think it is correct. However, one does
    have to take E_ALARM and E_INTR into account IIRC, so saying it is a
    either a FATAL error or all bytes are written is not true.

    But Rick never said that. That is what you made of it. Rick never talked
    about fatal errors, he talked about errors. I read his "errors" as
    "returns with an errorcode", in which case -- unless I'm completely
    mistaken -- he is spot on correct.

    M4

  13. Re: Help with FTP

    The question was, do you need to check for 'send' or 'write' returning
    fewer bytes than you asked it to send with blocking sockets. The
    answer is yes, because a non-fatal error may cause 'send' or 'write'
    to return after sending some, but not all, of the bytes send, and if
    you don't know how many bytes were sent, you cannot continue using the
    connection.

    If only a fatal error could do this, then the answer would be no.
    There's really no reason you would care how many bytes were queued
    prior to a fatal error, so the loss of that information would be loss
    of useless information. You would still detect the error the next time
    you tried to use the connection.

    DS

  14. Re: Help with FTP

    On Sat, 31 May 2008 18:35:33 -0700, David Schwartz wrote:

    > The question was, do you need to check for 'send' or 'write' returning
    > fewer bytes than you asked it to send with blocking sockets. The answer
    > is yes, because a non-fatal error may cause 'send' or 'write' to return
    > after sending some, but not all, of the bytes send, and if you don't
    > know how many bytes were sent, you cannot continue using the connection.
    >
    > If only a fatal error could do this, then the answer would be no.
    > There's really no reason you would care how many bytes were queued prior
    > to a fatal error, so the loss of that information would be loss of
    > useless information. You would still detect the error the next time you
    > tried to use the connection.


    Rereading the original posts, you are right. My technical insight was OK,
    but somehow my reading skills left me.

    M4

  15. Re: Help with FTP

    In all honesty when I posted I was not consciously thinking of EINTR
    and whether or not it is a fatal or not fatal error or more acurately
    though of as an exception.

    rick jones
    --
    web2.0 n, the dot.com reunion tour...
    these opinions are mine, all mine; HP might not want them anyway...
    feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...

+ Reply to Thread