I am writing two applications which needs to (among other things)
communicate through network, so one of them is a client and the other one is
a server. I have used asynchronous socket examples found at
http://msdn.microsoft.com/library/de...ketexample.asp
as templates (they have to be asynchronous, because application must not
freeze if connection fails). I have converted the client example into a
class which I call from windows form (where I use textboxes to specify the
server's IP address and textual message I want to send to the server) and
all the console.writeline's into messageboxes. I have also removed all the
echoing from the server because I don't need it. However, this only works if
both applications are running on the same machine. If this is not the case,
server application receives only the first message sent by client - if I
send the message again, client application gives me this exception:
System.Net.Sockets.SocketException: A request to send or receive data was
disallowed because the socket is not connected and (when sending on a
datagram socket using a sendto call) no address was supplied
at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset, Int32
size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at Test_Client.Client.Send(Socket sender, String data) in
D:\VBNET2003\Test_Client\Test_Client\Client.vb:lin e 144
at Test_Client.Client.Connect(String address, Int32 port, String message) in
D:\VBNET2003\Test_Client\Test_Client\Client.vb:lin e 49
If I use the synchronous client instead, I have no such problems. However,
client application would then hang if there are any connection problems, so
this doesn't seem to be a good option.
The whole client class code:
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
'State object for receiving data from remote device.
Public Class StateObject
' Client socket.
Public workSocket As Socket = Nothing
' Size of receive buffer.
Public BufferSize As Integer = 256
' Receive buffer.
Public buffer(256) As Byte
' Received data string.
Public sb As New StringBuilder
End Class 'StateObject
Public Class Client
' ManualResetEvent instances signal completion.
Private Shared connectDone As New ManualResetEvent(False)
Private Shared sendDone As New ManualResetEvent(False)
Private Shared receiveDone As New ManualResetEvent(False)
Public Shared Sub Connect(ByVal address As String, ByVal port As Integer,
ByVal message As String)
' Connect to a remote device.
Try
' Establish the remote endpoint for the socket.
' The name of the
' remote device is address.
Dim ipHostInfo As IPHostEntry = Dns.Resolve(address)
Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
Dim remoteEP As New IPEndPoint(ipAddress, port)
' Create a TCP/IP socket.
Dim sender As New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
' Connect to the remote endpoint.
sender.BeginConnect(remoteEP, AddressOf ConnectCallback, sender)
connectDone.WaitOne()
' Send test data to the remote device.
Send(sender, message & "<EOF>")
sendDone.WaitOne()
'release the socket.
sender.Shutdown(SocketShutdown.Both)
sender.Close()
Catch e As Exception
MessageBox.Show("Connect exception:" & e.ToString())
End Try
End Sub 'StartClient
Private Shared Sub ConnectCallback(ByVal ar As IAsyncResult)
Try
' Retrieve the socket from the state object.
Dim sender As Socket = CType(ar.AsyncState, Socket)
' Complete the connection.
sender.EndConnect(ar)
MessageBox.Show("Socket connected to " & sender.RemoteEndPoint.ToString())
' Signal that the connection has been made.
connectDone.Set()
Catch e As Exception
MessageBox.Show("ConnectCallback exception:" & e.ToString())
End Try
End Sub 'ConnectCallback
Private Shared Sub Send(ByVal sender As Socket, ByVal data As [String])
' Convert the string data to byte data using ASCII encoding.
Dim byteData As Byte() = Encoding.ASCII.GetBytes(data)
' Begin sending the data to the remote device.
sender.BeginSend(byteData, 0, byteData.Length, 0, _
AddressOf SendCallback, sender)
End Sub 'Send
Private Shared Sub SendCallback(ByVal ar As IAsyncResult)
Try
' Retrieve the socket from the state object.
Dim sender As Socket = CType(ar.AsyncState, Socket)
' Complete sending the data to the remote device.
Dim bytesSent As Integer = sender.EndSend(ar)
MessageBox.Show("Sent " & bytesSent & " bytes to server.")
' Signal that all bytes have been sent.
sendDone.Set()
Catch e As Exception
MessageBox.Show("SendCallback exception:" & e.ToString())
End Try
End Sub 'SendCallback
End Class 'Client
I use the code below to call the class from client application:
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnConnect.Click
Client.Connect(txtIP.Text, 1234, txtMessage.Text)
'I have also tried this, but it doesn't help in the least:
'Dim xCli As New Client
'xCli.Connect(txtIP.Text, 1234, txtMessage.Text)
'xCli = Nothing
End Sub
Any ideas how to resolve this? There was a winsock control in VB6 which
would be perfect for this, but it's absent in VB.NET, so I have to use
classes I don't truly understand.
Thanks in advance!