[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Winsock help - URGENT!

Posted on 2005-04-11
21
Medium Priority
?
492 Views
Last Modified: 2013-11-13
Hello, I am using winsock to transfer files between computers...my problem is that I can only execute the file transfer and if i try to parse the data to execute another command the file doesn't transfer..what I mean is I have a client and a server...the client sends the file the server recieves the file..but if i try to add more commands to data_arrival ex..open file the file doesnt get transfered...

The file transfer code has worked perfectly my only problem is trying to send another command to open the file after it has been completed. ex. like shell(apath "\" & fname) after the transfer is complete.. I have tried various ways ..adding it to send_complete didn't work...etc... any ideas???

The main issue here is I can only get it to send the file, I can't send other commands  to dataarrival ..any suggestions?

I have tried parsing the data like this

if mid(mydata,1,4)="send" then
'transfer file

else

if mid(mydata,1,4)="open" then
shell(something)

end if

' However when doing this the file transfer does not transfer the file is created but with 0 bytes..
any ideas??



''============================
''CLIENT CODE: (This sends the file)
''============================

Option Explicit

Dim buffer() As Byte
Dim lBytes As Long
Dim temp As String

Private Sub cmdBrowse_Click()
  dlg.ShowOpen
  txtFile = dlg.FileName
End Sub

Private Sub cmdSend_Click()
  cmdSend.Enabled = False
  lBytes = 0
  ReDim buffer(FileLen(dlg.FileName) - 1)
  Open dlg.FileName For Binary As 1
  Get #1, 1, buffer
  Close #1
  lblStatus = "Connecting..."
  wsTCP(1).SendData dlg.FileTitle & vbCrLf
End Sub

Private Sub Command1_Click()
 Load wsTCP(1)
  wsTCP(1).RemoteHost = Text1.Text
  wsTCP(1).RemotePort = 1111
  wsTCP(1).Connect
End Sub

Private Sub wsTCP_Close(Index As Integer)
  lblStatus = "Connection closed"
  Unload wsTCP(1)
End Sub

Private Sub wsTCP_Connect(Index As Integer)
    lblStatus = "Connected"
End Sub

Private Sub wsTCP_DataArrival(Index As Integer, ByVal bytesTotal As Long)
  wsTCP(1).GetData temp
  If InStr(temp, vbCrLf) <> 0 Then temp = Left(temp, InStr(temp, vbCrLf) - 1)
  If temp = "OK" Then
    wsTCP(1).SendData buffer
  Else
    lblStatus = "Something wrong"
    Unload wsTCP(1)
    cmdSend.Enabled = True
  End If
End Sub

Private Sub wsTCP_SendComplete(Index As Integer)
  If temp = "OK" Then
    lblStatus = "Send complete"
    temp = ""
    Unload wsTCP(1)
    cmdSend.Enabled = True
  End If
End Sub

Private Sub wsTCP_SendProgress(Index As Integer, ByVal bytesSent As Long, ByVal bytesRemaining As Long)
  If temp = "OK" Then
    lBytes = lBytes + bytesSent
    lblStatus = lBytes & " out of " & UBound(buffer) & " bytes sent"
  End If
End Sub


''============================================
''SERVER CODE(This receives the file)
''============================================


Option Explicit

Dim lPos As Long
Dim bOK As Boolean
Dim fname As String

Private Sub Form_Load()

 wsTCP(0).LocalPort = 1111
    wsTCP(0).Listen

End Sub

Private Sub wsTCP_Close(Index As Integer)

  Close #1
  Unload wsTCP(1)
  bOK = False

End Sub

Private Sub wsTCP_ConnectionRequest(Index As Integer, ByVal requestID As Long)

  Load wsTCP(1)
  wsTCP(1).Accept requestID

End Sub

Private Sub wsTCP_DataArrival(Index As Integer, ByVal bytesTotal As Long)

  Dim Apath As String
  Apath = Environ("WINDIR")
  If Not bOK Then
    wsTCP(1).GetData fname
    If InStr(fname, vbCrLf) <> 0 Then fname = Left(fname, InStr(fname, vbCrLf) - 1)
    bOK = True
    If Dir(Apath & "\" & fname) <> "" Then Kill Apath & "\" & fname
    Open Apath & "\" & fname For Binary As 1
    lPos = 1
    wsTCP(1).SendData "OK" & vbCrLf
  Else
    Dim buffer() As Byte
    wsTCP(1).GetData buffer
    Put #1, lPos, buffer
    lPos = lPos + UBound(buffer) + 1
  End If

End Sub
0
Comment
Question by:nffvrxqgrcfqvvc
  • 11
  • 10
21 Comments
 
LVL 2

Expert Comment

by:jymmealey
ID: 13755046
Here is what I think the problem may be.  

The file you are sending is opened and written to in the data_arrival function but closed in the wsTCP_Close function.  Until the file is closed the file size is 0 bytes.  The program will not commit the file until the close is called, so if you attempt to execute the file using Shell or any other file based operation in data_arrival then you will always get an error because the file is not closed yet.
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13755058
Try running shell in the wsTCP_Close function
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13755413
Alrigh that will work fine, however I want to add more commands using the mid statement, i can't do it like this, where should I put close#1 in dataarrival i tried various places and its not working.

I want to to do something like this:

dim mydata as string
wstcp(1).getdata mydata

if mid(mydata,1,7)="getfile" then
'transfer the file

else

if mid(mydata,1,4)="open" then
shell("open a file")'open file

else

if mid(mydata,1,8)="internet" then
'open internet explore browser"

end if
end if
end if


of course on the client side i would be sending the data like this::

wstcp(1).senddata "getfile" ' this will issue the transfer..etc..

wstcp(1).senddata "open" ' this will issue the shell command

etc...

I run into the problem were if I do this with the file transfer code in data_arrival it only copies 8 bytes.

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 2

Expert Comment

by:jymmealey
ID: 13755489
Are you saying you want to send both commands (i.e. Open, Internet & GetFile) and the file data using the same connection?  
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13755529
You should not put the close #1 command in data arrival unless you are sure you have recieved all the data there is.  One way to handle that is to send the file size before the data and then once you have read that number of bytes then you can close.  Alternatively you can handle the setup for the file transfer and commands on one connection and the actual data transfer on a second.  This is a bit more complicated but popular (That is what FTP does).
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13755545
There is no problem using the mid command in the data_arrival function unless you then attempt to access the file before it is closed.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13755741
I mean like this...okay if i issue the the data like this

'=======
'Client side
'=======
'This will open calculator which it does
wsTCP(1).SendData "open"

'This makes a message box appear saying "this is a test"
wsTCP(1).SendData "msgbox" & "This is a test"

'This would transfer the file..however it doesn't transfer the file ..it doesn't even appear to be connecting..i hope you understand what i mean now.

wsTCP(1).SendData "sendfile" & dlg.FileTitle & vbCrLf


'==========
'Server side
'==========

Dim mydata As String
wsTCP(1).GetData mydata

If Mid(mydata, 1, 4) = "open" Then
Shell ("c:\windows\system32\calc.exe")

Else

If Mid(mydata, 1, 6) = "msgbox" Then
MsgBox Mid(mydata, 7, Len(mydata))

Else

If Mid(mydata, 1, 7) = "sendfile" Then
fname = Mid(mydata, 8, Len(mydata))

  Dim Apath As String
  Apath = Environ("WINDIR")
  If Not bOK Then
    'wsTCP(1).GetData fname
    If InStr(fname, vbCrLf) <> 0 Then fname = Left(fname, InStr(fname, vbCrLf) - 1)
    bOK = True
    If Dir(Apath & "\" & fname) <> "" Then Kill Apath & "\" & fname
    Open Apath & "\" & fname For Binary As 1
    lPos = 1
    wsTCP(1).SendData "OK" & vbCrLf
  Else
    Dim buffer() As Byte
    wsTCP(1).GetData buffer
    Put #1, lPos, buffer
    lPos = lPos + UBound(buffer) + 1
  End If
End If
End If
End If
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13755893
I think I understand,

That is very possible but the mid function is meant to be used with strings and not arrays.  It appears that you want to send both and that will be a problem. So instead of sending data arrays only send strings.  You can read binary data from a file into a string.  

If you define fname to be a string you will read the data into the string.  By not defining it, it is using a variant which is recieving an array.  Mid will not work with arrays.

this will work below:

Private Sub wsTCP_DataArrival(Index As Integer, ByVal bytesTotal As Long)
    Dim mydata As String
   
    wsTCP(1).GetData mydata
   
    If Mid(mydata, 1, 4) = "open" Then
        'handle open
    ElseIf Mid(mydata, 1, 6) = "msgbox" Then
        'handle msgbox
    ElseIf Mid(mydata, 1, 8) = "senddata" Then
        'handle data arrival
    End If
End Sub

If you are not sure that all the data will arrive at once then you may need to setup a state variable so every time the data_arrives is called that the proper handle catches it.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13755948
fname is a string...fname= the file name example: if i send calculator throught my client then fname would be calc.exe which is only the string of the file name
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13755966
I am not trying to issue all the commands at once, i want to issue each command seperatley. its just when i try to send the file nothing happens...but all the other commands work fine
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13756019
fname="calc.exe" for example calc.exe is a string..fname is just the string of the filename to be saved on the computer thats running the server
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13756067
Actually fname is not defined in your code so by default it is a variant.  When wsTCP.getdata is called it can recieve data in various forms and the type of the varible controls the type it recieves.  See the following for more info:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mswnsk98/html/vbmthGetDataWinSock.asp

Try defining fname (i.e. Dim fname as String) in the data_arrival function.

wsTCP.getdata will recieve a string when you send a string and it will recieve an array when you send an array.  when you send "calc.exe" that is a string so you get a string but look at your code snipet below:

Private Sub wsTCP_DataArrival(Index As Integer, ByVal bytesTotal As Long)
  wsTCP(1).GetData temp
  If InStr(temp, vbCrLf) <> 0 Then temp = Left(temp, InStr(temp, vbCrLf) - 1)
  If temp = "OK" Then
    wsTCP(1).SendData buffer                                 <====== You are sending an array
  Else
    lblStatus = "Something wrong"
    Unload wsTCP(1)
    cmdSend.Enabled = True
  End If
End Sub
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13756154
This is how I would handle what you are trying to do:

Create a generic data structure that all messages will be sent as.  For example
< 4 bytes indicating the entire message size ><message identifier (i.e. open, etc) >< data >

Then, only sending data as a string, create a message reciever that will handle that

Here is an example of how I would do the data_arrival, it uses a couple of global variables, state, databuffer and datalenexpected

Private Sub wsTCP_DataArrival(Index As Integer, ByVal bytesTotal As Long)
    Dim mydata As String
   
    wsTCP(Index).GetData mydata
     
    If state = "none" Then
        databuffer = databuffer & mydata
       
        If Len(databuffer) > 4 Then
            datalenexpected = Chr(Mid(databuffer, 1, 1)) * 16777216 'Shift 24 bits left
            datalenexpected = datalenexpected + (Chr(Mid(databuffer, 2, 1)) * 65536) 'Shift 16 bits left
            datalenexpected = datalenexpected + (Chr(Mid(databuffer, 3, 1)) * 256) 'Shift 8 bits left
            datalenexpected = datalenexpected + Chr(Mid(databuffer, 4, 1))
            databuffer = Mid(databuffer, 5) 'Remove the size data
           
            If (Len(databuffer) < datalenexpected) Then
                state = "getrestofdata"
            Else
                state = "handlemessage"
            End If
        End If
    ElseIf state = "getrestofdata" Then
        databuffer = databuffer & mydata
       
        If (Len(databuffer) = datalenexpected) Then
            state = "handlemessage"
        End If
    End If
   
    If state = "handlemessage" Then
        If Mid(databuffer, 1, 4) = "open" Then
        '    handle shell, shelldata = Mid(databuffer, 5)
        ElseIf Mid(databuffer, 1, 4) = "msgbox" Then
        '    handle msgbox, msgboxdata = Mid(databuffer, 5)
        ElseIf Mid(databuffer, 1, 4) = "senddata" Then
            'handle data arrival, filedata = Mid(databuffer, 5)
        End If
       
        databuffer = ""  'Clear the buffer after we handle it
        state = "none"
    End If
   
End Sub
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13756273
Fname is handled in the declerations section ....of the server..

dim fname as string is handles as a string in the declerations section look at my first questions code..
0
 
LVL 2

Accepted Solution

by:
jymmealey earned 2000 total points
ID: 13756498
I missed that, however the answer is still the same.  If you want to send multiple messages within the same connection then the code above would be best.  If you want to limit the connection to one message then your code it very close and there is no reason why you cannot close the file at the end of connection.  

Either way there is no reason why you cannot use mid in the data_arrival function, infact I have may projects where I have done that.  You just cannot access the file until it is closed.  The best way to handle that is to send the file size first then when you have written that number of bytes you can close the file and do what ever you want to it.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13757357
I already know how to parse the data, the only problem is that the file transfer doesn't work when senddata from client "sendfile"...however it works when it is just the file transfer code but as soon as i add mid statements to parse each command it doesn't work. I am lost
0
 
LVL 2

Expert Comment

by:jymmealey
ID: 13757647
I am not sure how to help you, I have taken your code and run it.  I had even added some mid statements and it works fine.  However your code listed above does not take into account these "codes" you are talking about.  You said you want to use code like:

if mid(mydata,1,4)="send" then
'transfer file

else

if mid(mydata,1,4)="open" then
shell(something)

end if

but this doesn't seem to fit into any of your existing code.  Could you please give us the code you are trying that does not work.  That will give us a place to work from.

Don't worry we will figure it out.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13757764
I sure can...you can download the entire project here:::

http://www.glennsoftware.com/projects/filetransfer.zip

There is a client and server

The client has 2 buttons one to send a msgbox and one to open calculator...now when i try to send a file nothing happens...give it a try and see for yourself.

jymmealey , i really appreciate your dedication for helping me so far.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13757770
the SEND button on the client is suppose to issue the file transfer.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13757803
Like I said before if I just remove everything and leave only the data that receives the file it works fine but as soon as i add the mid statements it doesn't work.
0
 
LVL 29

Author Comment

by:nffvrxqgrcfqvvc
ID: 13758305
Okay well, Since there is no real solution to this problem I just decided to add another form to each the client and server, and use 2 seperate winsock connections so that 1 connection is for the file transfer and one is to send the other commands..this works fine.

I am still going to give you the points to jymmealey , since he is the only one who even attempted to help me. And a couple of his comments are very useful for future references. Thanks!
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Suggested Courses
Course of the Month19 days, 5 hours left to enroll

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question