-
Winsock and File Transfers
I've been trying to make a program over the past week that reads a file and sends it via Winsock to another IP. I've had luck with Winsock in transferring small portions of text but I can't seem to get it to do the same with files. Here's the code I've written for this.
Code:
Imports System.IO
Public Class FileTransfer
Const BYTE_SIZE As Integer = 8000
Dim remoteSaveAs As String = ""
' sends the file
Private Sub transferButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles transferButton.Click
Dim saveAs As String = saveAsTextBox.Text
Dim fileName As String = fileTextBox.Text
Dim filestream As System.IO.FileStream = Nothing
Dim buffer(BYTE_SIZE - 1) As Byte
Dim bytesRead As Integer = 0
Dim totalBytesRead As Long = 0
If saveAs = "" Then
MsgBox("You must enter a name to save the file as", MsgBoxStyle.Critical, "Error")
End If
filestream = New System.IO.FileStream(fileName, _
IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Try
Do
bytesRead = filestream.Read(buffer, 0, BYTE_SIZE)
If (bytesRead > 0) Then
FTWinsock2.SendData(saveAs)
FTWinsock.SendData(buffer)
totalBytesRead += bytesRead
buffer = Nothing
End If
Loop While bytesRead > 0
Catch ex As Exception
MsgBox("ERROR", MsgBoxStyle.Critical, "ERROR")
Me.Hide()
End Try
End Sub
' receives file
Private Sub FTWinsock_DataArrival(ByVal sender As Object, _
ByVal e As AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent) _
Handles FTWinsock.DataArrival
Dim buffer(BYTE_SIZE - 1) As Byte
Dim filestream As System.IO.FileStream = Nothing
filestream = New System.IO.FileStream(remoteSaveAs, _
IO.FileMode.Open, IO.FileAccess.Write, IO.FileShare.Write)
FTWinsock.GetData(buffer)
filestream.Write(buffer, 0, BYTE_SIZE)
End Sub
' establishes connection
Private Sub FileTransfer_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'Sets the Host
Dim IPAddress As String = InputBox("Please input the IP of the other computer.")
If IPAddress = "" Then
IPAddress = InputBox("You must enter an IP address.")
FTWinsock.RemoteHost = IPAddress
FTWinsock2.RemoteHost = IPAddress
Else
FTWinsock.RemoteHost = IPAddress
FTWinsock.RemoteHost = IPAddress
End If
End Sub
Private Sub selectFileButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles selectFileButton.Click
Dim fileName As String = ""
Dim OpenFileDialog As New OpenFileDialog()
If OpenFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
fileName = OpenFileDialog.FileName
fileTextBox.Text = fileName
End If
End Sub
Private Sub FTWinsock2_DataArrival(ByVal sender As Object, _
ByVal e As AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent) _
Handles FTWinsock2.DataArrival
If remoteSaveAs = "" Then
FTWinsock2.GetData(remoteSaveAs)
End If
End Sub
End Class
When I run this I get a System.Runtime.IntropServices.COMException. Prior to this code I had another version that read the entire file into the buffer and then sent it. That code gave me a System.Reflection.TargetException, so I assumed I was sending too much at once and made this to send the file in chunks instead. Is Winsock just not a good method to send files with? What am I doing wrong?
-
Re: Winsock and File Transfers
Doesn't seem right to me. Download the samples, and take a look.
http://code.msdn.microsoft.com/vb2010samples
-
Re: Winsock and File Transfers
Use the System.Net.Sockets class.
-
Re: Winsock and File Transfers
Quote:
Originally Posted by
DataMiser
Use the System.Net.Sockets class.
Ok I'm a little unfamiliar with that class. I'm able to set up the client side ok but I can't figure out how to get the listener to retrieve and save the bytes as they're coming in.
-
Re: Winsock and File Transfers
Your listener should accept the connection at which point that connection [socket] is what will be receiving data, the listener will keep on listening for other connections.
There are samples included with VS.
-
Re: Winsock and File Transfers
Ok I got that working. One more thing though. I was only able to connect to the local host using sockets. Is it possible to connect to a remote IP?
-
Re: Winsock and File Transfers
Yes, I do it all the time.
-
Re: Winsock and File Transfers
Good I'm glad to hear that. Well here's my specific problem. Every time I enter a remote IP to listen on the TcpListener refuses to start and throws a SocketException. I've tried both IPAddress.Parse("IP String") and IPAddress.Any but get the same result. Any idea what might be happening here?
-
Re: Winsock and File Transfers
You put the listener on the server, and can connect to it from other IP's
-
Re: Winsock and File Transfers
Yes the Listener uses the local address and clients connect to it be they local or remote by issuing a connection request to the IP of the listener.
-
Re: Winsock and File Transfers
Hmm, now my connection request is being refused by the server. This would seem like a firewall problem but I disabled it for a couple minutes and it still refused it. Would being connected through a router cause a problem?
-
Re: Winsock and File Transfers
It could, depends on what port you are using, also depends on if it is the client on the other side of the router or the listener. If both are on the same side of the router then should not be a concern.
-
Re: Winsock and File Transfers
Use the PING command. PING /?
Might be Windows Firewall, or AV
-
Re: Winsock and File Transfers
Quote:
Originally Posted by
DataMiser
It could, depends on what port you are using, also depends on if it is the client on the other side of the router or the listener. If both are on the same side of the router then should not be a concern.
So are you saying that some ports don't work? I was using 13000.
-
Re: Winsock and File Transfers
The firewall in most routers block some ports by default. I can't tell you much as I do not have any idea of what your test environment is actually like. Typically a rejected message could indicate that your listener is not running.
-
Re: Winsock and File Transfers
Most routers are open to the normal protocols
-
Re: Winsock and File Transfers
Ok well I've tested this a few different ways but haven't gotten anywhere. I don't think it's the router though because I turned off its firewall (and the computer's again) to test this. I also tested it on different computers both inside and outside the router with the same result. To me it seems like VB is purposely rejecting it. Is it possible for that to occur?
-
Re: Winsock and File Transfers
Show some of your code and maybe someone can help. At the moment you are not giving us much to go on. If you could show the part of your client code that attempts the connection and the part of your server code that accepts the connection then we might have an idea of how to direct you. As is for all we know your code is not accepting the connection.
-
Re: Winsock and File Transfers
I thought I should have posted this earlier. Alright here's the code.
First the client side.
Code:
Private Sub transferButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles transferButton.Click
Const BYTE_SIZE As Integer = 1
Dim stream As NetworkStream
Dim fileToSend As String = fileToSendTextBox.Text
Dim saveAs As String = saveAsTextBox.Text
Dim IPAddress As String = "24.129.26.34"
Dim filestream As System.IO.FileStream = Nothing
Dim buffer(BYTE_SIZE - 1) As Byte
Dim bytesRead As Integer = 0
Dim port As Int32 = 13000
Dim client As New TcpClient
client.Connect(IPAddress, port)
If fileToSend = "" Then
MsgBox("You must choose a file", MsgBoxStyle.Critical, "Error")
End If
stream = client.GetStream()
filestream = New System.IO.FileStream(fileToSend, _
IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Try
Do
bytesRead = filestream.Read(buffer, 0, BYTE_SIZE)
If (bytesRead > 0) Then
stream.Write(buffer, 0, BYTE_SIZE)
End If
Loop While bytesRead > 0
Catch ex As Exception
MsgBox("ERROR", MsgBoxStyle.Critical, "ERROR")
Me.Hide()
End Try
End Sub
And now the server
Code:
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim stream As NetworkStream
Dim server As TcpListener
Dim port As Int32 = 80
Dim IP As IPAddress = IPAddress.Parse("127.0.0.1")
server = New TcpListener(IP, port)
server.Start()
While True
Dim i As Int32
Dim client As TcpClient = server.AcceptTcpClient()
stream = client.GetStream()
i = stream.Read(bytes, 0, bytes.Length)
While (i <> 0)
Write()
i = stream.Read(bytes, 0, bytes.Length)
End While
client.Close()
End While
-
Re: Winsock and File Transfers
Your server side code looks rather odd.
Here are some snippets from my server code.
In my server start routine I have
Code:
SocketHandler = New TcpListener(hIPAddress, hPort) ' Set the IP AND Port Number
SocketHandler.Start()
I have a timer running which checks to see if there are any pending connections every 100ms.
Code:
If SocketHandler.Pending() Then
CurThreadStart = New ThreadStart(AddressOf ConnectionBegin) ' Set info for the new thread
CurThread = New Thread(CurThreadStart) ' Initialize the new thread variable
CurThread.SetApartmentState(ApartmentState.STA)
CurThread.Start() ' Start the thread
SyncLock CurThread ' Lock the thread for update
VAActiveThreads += 1 ' increment active threads
cInfo.ActiveClients += 1
CurThread.Name = "ClientCon" + VAActiveThreads.ToString ' Name the thread
Console.WriteLine(CurThread.Name & " Thread Started")
End SyncLock
End If
Then in my ConnectionBegin which is launched by the code above in a new thread I have.
Code:
Dim ClientSocket As Socket = SocketHandler.AcceptSocket
Followed by a loop that will read from the port until there is a idle timeout condition.
-
Re: Winsock and File Transfers
Code:
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
server = New TcpListener(IP, port)
server.Start()
End Sub
Private Sub FTTimer_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles FTTimer.Tick
If server.Pending() Then
threadStart = New ThreadStart(AddressOf ConnectionBegin)
thread = New Thread(threadStart)
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
End If
End Sub
Private Sub ConnectionBegin()
While True
Dim i As Int32
Dim client As TcpClient = server.AcceptTcpClient()
stream = client.GetStream()
i = stream.Read(bytes, 0, bytes.Length)
While (i <> 0)
Write()
i = stream.Read(bytes, 0, bytes.Length)
End While
client.Close()
End While
End Sub
Is this slightly better? Even with the addition of a pending check, the listener still can't seem to "hear" that remote connection.
-
Re: Winsock and File Transfers
What's with the while true loop? You need to ditch that.
-
Re: Winsock and File Transfers
Duh... I just reviewed your code posted earlier and I see a problem with your port assignments.
Your server is listening on port 80 but your client is trying to connect on port 13000.
You must use the port that the listener is actually listening on if you expect a connection as well as the IP that the server is on.
-
Re: Winsock and File Transfers
Also looks like there is a problem with your IP address.
If your server is on IP 123.456.789.0 and is Listening on Port 24000 then your client would need to try to connect to IP 123.456.789.0 on Port 24000.
If your client trys to connect to IP 456.123.789.0 It will not connect because that is not where your server is at. If your client tries to connect on port 1234 if will not connect because that is not the port you are listening to.
-
Re: Winsock and File Transfers
I'm a little confused now. I fixed the port mistake, but I don't quite get what you mean when you say there's something wrong with my IP. I AM supposed to be listening on the localhost correct? The way I have it setup my server listens on the localhost and the client connects to it via the server's remote IP.
-
Re: Winsock and File Transfers
Quote:
If your server is on IP 123.456.789.0 and is Listening on Port 24000 then your client would need to try to connect to IP 123.456.789.0 on Port 24000.
That means, for you code to work, your server would have to be IP 123.456.789.0 on Port 24000 (on the server)
-
Re: Winsock and File Transfers
Quote:
Originally Posted by
Murjax
I'm a little confused now. I fixed the port mistake, but I don't quite get what you mean when you say there's something wrong with my IP. I AM supposed to be listening on the localhost correct? The way I have it setup my server listens on the localhost and the client connects to it via the server's remote IP.
The client would use the address of the server. If your server address is 127.0.0.1 as in your example above then your client would have to use 127.0.0.1
For example If you want to connect to Google you will not get there by typing in Yahoo.
Btw you can also use the machine name rather than a hard coded IP address. Works much better especially when the IP is DHCP controlled.
Code:
Dim hInfo As IPHostEntry = Nothing
Dim hIPAddress As IPAddress = Nothing
hInfo = Dns.GetHostEntry("Machine Name Here")
hIPAddress = hInfo.AddressList(0)
-
Re: Winsock and File Transfers
That's how I originally thought the connection was supposed to work. The problem (as I stated some posts back) is that when I have the server listen on any IP other than 127.0.0.1 a SocketException is thrown saying that "The requested address is not valid in its context".
-
Re: Winsock and File Transfers
You must use an address that is valid on the machine where the server is being executed. This is your Local Host. The client must use that same IP address and port as the parameters for the connection.
Here is a bit of code from my server. Note I do not hard code any IP address.
Code:
Dim hInfo As System.Net.IPHostEntry = Dns.GetHostEntry(Dns.GetHostName)
Dim hIPAddress As IPAddress = Nothing
hIPAddress = hInfo.AddressList(0)
SocketHandler = New TcpListener(hIPAddress, hPort) ' Set the IP AND Port Number
SocketHandler.Start()
-
Re: Winsock and File Transfers
The question should have been WHEN DO I USE 127.0.0.1 on Both the CLIENT AND THE HOST?
That answer would be when both are running on the SAME MACHINE. You can run client and server on the same machine.
-
Re: Winsock and File Transfers
I understand that when both the client and server are on the same machine I use 127.0.0.1. I've gotten that to work. My goal though is for it to work when the client and server are on different machines. If the server can only listen on the local host then how does a client connect to the server's local host if the client is on a different machine?
BTW I've decided to use hInfo.AddressList(0) example given to make it simpler.
-
Re: Winsock and File Transfers
The instances I have shown where I used the
Code:
hInfo = Dns.GetHostEntry(Dns.GetHostName)
for the server
and
Code:
hInfo = Dns.GetHostEntry("Server Machine Name or IP here")
for the client
Work on the same machine as well as different machines. I have been using this method or one very similar to it for a very long time at several client locations and many pcs without fail.
The client method works on PCs, Windows CE devices, Windows Mobile Devices as well as the emulators when configured properly. I even have a few that are using this over wan connections without issue.
Note in all cases I am using the System.Net.Sockets class and not the TCP client though for connection purposes I would expect this to work with the TCP client as well.
Also note that on the client I use a varible for the host name that would be contained in a cfg file of sorts so as to make it easy to change as needed.
-
Re: Winsock and File Transfers
Usually, a ConnectionString variable, so you can switch easily, in one place.
-
Re: Winsock and File Transfers
It works now. Thanks for your help.