VB.Net FTP login Class almost works, need help

I found this sample class file code online and it almost works. That is, it works when I step through the code in debug mode on my VS 2005. The output I get in debug mode looks like this:
USER ftpUser
220 Microsoft FTP Service
331 Password required for ftpUser.
PASS ftpPassword
230 User ftpUser logged in.
However, when I run it without debugging it fails and I get this:
USER ftpUser
220 Microsoft FTP Service
PASS ftpPassword
331 Password required for ftpUser.
It looks like the password is being sent before the 331 response.
Should I add code to check for the 331 response before sending the password or am I mistaken about the problem? How do I check for the 331?

Public Class ftpCreate
    Private ftpTcpClient As TcpClient
    Public ResponseStream As NetworkStream
    Public ReturnNameMessage As String
    Public ReturnPwdMessage As String

    Public Sub ftpLogin(ByVal strName As String, ByVal strPWD As String, ByVal strftpLogin As String)
        Try
            Dim strCommand As String
            Dim strReturnMessage As String
            Dim bteSendBytes() As Byte
            Dim bteReturnBytes() As Byte
            Dim intReturnByteLength As Integer
            Dim ftpTcpClient As TcpClient = New TcpClient(strftpLogin, 21)
            ResponseStream = ftpTcpClient.GetStream
            strCommand = "USER " + strName + vbCrLf
            bteSendBytes = Encoding.ASCII.GetBytes(strCommand)
            ResponseStream.Write(bteSendBytes, 0, bteSendBytes.Length)
            intReturnByteLength = ftpTcpClient.ReceiveBufferSize
            ReDim bteReturnBytes(intReturnByteLength)
            ResponseStream.Read(bteReturnBytes, 0, intReturnByteLength)
            strReturnMessage = Encoding.ASCII.GetString(bteReturnBytes) + "/ "
            ReturnNameMessage = strCommand + strReturnMessage
            strCommand = "PASS " + strPWD + vbCrLf
            Array.Clear(bteSendBytes, 0, bteSendBytes.Length)
            bteSendBytes = Encoding.ASCII.GetBytes(strCommand)
            ResponseStream.Write(bteSendBytes, 0, bteSendBytes.Length)
            intReturnByteLength = ftpTcpClient.ReceiveBufferSize
            ReDim bteReturnBytes(intReturnByteLength)
            ResponseStream.Read(bteReturnBytes, 0, intReturnByteLength)
            strReturnMessage = Encoding.ASCII.GetString(bteReturnBytes) + "/ "
            ReturnPwdMessage = strCommand + strReturnMessage + vbCrLf
        Catch ex As SocketException
            ReturnPwdMessage = ex.Message
        End Try
    End Sub

End Class

Open in new window

LVL 38
Tom BeckAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CodeCruiserCommented:
Try adding a Thread.Sleep(500) call to add some delay before sending the password.
0
Tom BeckAuthor Commented:
CodeCruiser,
That works when the delay is added immediately after the USER is sent but before the response is read (didn't work further down than that in the process). My concern is this. I am writing a utility that will be offered to others. What if someone has a really slow connection. How much delay would be required to cover all possibilities? Instead, is there a way to check that the response on the USER request is complete with the 331 before sending the password?
0
CodeCruiserCommented:
Try adding this check

If strReturnMessage.StartsWith("331") Then
   'send password
End If
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

Tom BeckAuthor Commented:
CodeCruiser,
The code below is my attempt to combine both of your suggestions. It adds a half second delay if the strReturnMessage does not contain 331 but limits the total delay to 10 seconds so it's not waiting forever. On my connection, it's adding one half second delay before sending the password. It works.
I am a novice programmer, so tell me if I don't have all bases covered.
Thanks for the help.
Public Class ftpCreate
    Private ftpTcpClient As TcpClient
    Public ResponseStream As NetworkStream
    Public ReturnNameMessage As String
    Public ReturnPwdMessage As String

    Public Sub ftpLogin(ByVal strName As String, ByVal strPWD As String, ByVal strftpLogin As String)
        Try
            Dim strCommand As String
            Dim strReturnMessage As String = ""
            Dim bteSendBytes() As Byte
            Dim bteReturnBytes() As Byte
            Dim intReturnByteLength As Integer
            Dim timeCheck As Integer = 0
            Dim ftpTcpClient As TcpClient = New TcpClient(strftpLogin, 21)
            ResponseStream = ftpTcpClient.GetStream
            strCommand = "USER " + strName + vbCrLf
            bteSendBytes = Encoding.ASCII.GetBytes(strCommand)
            ResponseStream.Write(bteSendBytes, 0, bteSendBytes.Length)
            intReturnByteLength = ftpTcpClient.ReceiveBufferSize
            ReDim bteReturnBytes(intReturnByteLength)
            Do Until strReturnMessage.Contains("331")
                ResponseStream.Read(bteReturnBytes, 0, intReturnByteLength)
                strReturnMessage = Encoding.ASCII.GetString(bteReturnBytes) + "/ "
                System.Threading.Thread.Sleep(500)
                timeCheck = timeCheck + 500
                If timeCheck > 10000 Then
                    ReturnNameMessage = "User " & strName & " not accepted, timed out."
                    Exit Try
                Else
                    ReturnNameMessage = strCommand + strReturnMessage
                End If
            Loop
            timeCheck = 0
            strCommand = "PASS " + strPWD + vbCrLf
            Array.Clear(bteSendBytes, 0, bteSendBytes.Length)
            bteSendBytes = Encoding.ASCII.GetBytes(strCommand)
            ResponseStream.Write(bteSendBytes, 0, bteSendBytes.Length)
            intReturnByteLength = ftpTcpClient.ReceiveBufferSize
            ReDim bteReturnBytes(intReturnByteLength)
            ResponseStream.Read(bteReturnBytes, 0, intReturnByteLength)
            strReturnMessage = Encoding.ASCII.GetString(bteReturnBytes) + "/ "
            ReturnPwdMessage = strCommand + strReturnMessage + vbCrLf
        Catch ex As SocketException
            ReturnPwdMessage = ex.Message
        End Try
    End Sub

End Class

Open in new window

0
Tom BeckAuthor Commented:
Actually, this Do loop works better because it only adds the delay when necessary.
...
            Do Until strReturnMessage.Contains("331")
                If timeCheck > 10000 Then
                    ReturnNameMessage = "User " & strName & " not accepted, timed out."
                    Exit Try
                Else
                    ResponseStream.Read(bteReturnBytes, 0, intReturnByteLength)
                    strReturnMessage = Encoding.ASCII.GetString(bteReturnBytes) + "/ "
                    If Not strReturnMessage.Contains("331") Then
                        System.Threading.Thread.Sleep(500)
                        timeCheck = timeCheck + 500
                    End If
                    ReturnNameMessage = strCommand + strReturnMessage
                End If
            Loop
            ...

Open in new window

0
CodeCruiserCommented:
The approach looks good to me. You may be novice but the good thing is that you just needed a hint to write your own code. You may want to implement this logic for all of the commands that you send so that you wait for response before sending the next command.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
File Sharing Software

From novice to tech pro — start learning today.