sockets problem

D

Dmitry Akselrod

Hello everyone,

I have a vb.net application that wraps the TCPListener object
in a class. The server connects to the local interface and establishes
itself on port 9900. It then polls for pending connections every 500ms.

I also have a vb6 application that uses the WinSock control at the other end
of the communication tunel. I have to work with vb6 here because it uses
less memory than .NET.

The WinSock control is not able to fully connect to the vb.net TCPListener.
The winsock.state is
constantly 6 (connecting). Thus I can never send a message to the .net
TCPlistener.

What's interesting is that:
a. I can do the reverse and connect to a vb6 WinSock control from vb.net
TCPClient and communicate without any issues.
b. According to debug information in .net the vb.net TCPListener
establishes a connection with the vb6 winsock control, but in vb6 world the
vb6 control thinks the status is "connecting"

Here is the .net Class that functions as the TCP server:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Imports System.Net.Sockets
Imports System.Text
Imports System.Net
Imports Microsoft.VisualBasic.Strings
Imports ControlChars = Microsoft.VisualBasic.ControlChars
Imports PrintMonitor.DataBaseConnection

Public Class SocketServer

' This class will control the WinSock server
' The server will answer client requests, such as request for a list of
project numbers

' default server binding is to the first ethernet interface and port
9900
Private ipAddress As ipAddress =
Dns.Resolve(Dns.GetHostName).AddressList(0)
Private Const PortNumber As Integer = 9900

' tcp server
Private TCPServer As TcpListener

Private IsListening As Boolean = False
Private PollTimer As New Timer()

' the client that initiates the connection
Private tcpClient As tcpClient
Private tcpSocket As Socket

' networkstream object
Private NetworkStream As NetworkStream

' Client Messages
Private Const ProjectListRequest As String = "REQUEST:pROJECT_LIST"
Private Const ExitRequest As String = "EXIT"

'repro database connection
Private db As New PrintMonitor.DataBaseConnection()

Public Sub New()

' initialize the server
Try
TCPServer = New TcpListener(ipAddress, PortNumber)
Catch e As System.Net.Sockets.SocketException
MessageBox.Show(e.Message)
End Try

'initialize timer
PollTimer.Interval = 500
PollTimer.Enabled = True

AddHandler PollTimer.tick, AddressOf PollTimer_Tick

End Sub

'overloaded
Public Sub New(ByVal ipAddress As ipAddress, ByVal PortNumber As
Integer)

' initialize the server
Try
TCPServer = New TcpListener(ipAddress, PortNumber)
Catch e As System.Net.Sockets.SocketException
MessageBox.Show(e.Message)
End Try

'initialize timer
PollTimer.Interval = 500
PollTimer.Enabled = True

AddHandler PollTimer.Tick, AddressOf PollTimer_Tick

End Sub

Public Sub startListening()
Try
TCPServer.Start()
Console.WriteLine("SERVER>listening on interface " &
ipAddress.ToString & _
" on port " & PortNumber.ToString & ".....")
IsListening = True
Catch e As System.Net.Sockets.SocketException
MessageBox.Show(e.Message)
End Try

' start the timer
PollTimer.Start()
End Sub

Public Sub stopListening()

If IsListening Then
TCPServer.Stop()
End If
IsListening = False

End Sub

Private Sub PollTimer_Tick(ByVal sender As Object, ByVal e As
System.EventArgs)

PollTimer.Start()

' if a conenction is pending, start a new thread and process
connection
If TCPServer.Pending Then

Dim tCheckForConnectionThread As System.Threading.Thread
tCheckForConnectionThread = New
System.Threading.Thread(AddressOf ProcessConnection)
tCheckForConnectionThread.IsBackground = True
tCheckForConnectionThread.Name = "Checking for Connection <" & _
System.DateTime.Now.ToString & ">"
tCheckForConnectionThread.Start()

'CheckForConnection()
End If

End Sub

Private Sub ProcessConnection()
If TCPServer.Pending Then
Try

tcpSocket = TCPServer.AcceptSocket
Console.WriteLine("SERVER>Connection accepted.")

' get and convert the message to a string for processing
Dim bReceivedBytes(1024) As Byte
If tcpSocket.Available > bReceivedBytes.Length Then
Console.WriteLine("ERROR: Received byte stream larger
than buffer. " & _
"Trancation has occured.")
End If
tcpSocket.Receive(bReceivedBytes)

Dim sStreamData As String =
Encoding.ASCII.GetString(bReceivedBytes)
AnalyzeClientMessage(sStreamData)

Catch e As System.Net.Sockets.SocketException
MessageBox.Show(e.Message.ToString)
End Try
End If

'clean up and kill the current thread
If Not IsNothing(tcpSocket) Then
If tcpSocket.Connected Then
Console.WriteLine("Closing Connection." )
tcpSocket.Close()
End If
End If
System.Threading.Thread.CurrentThread.Abort()
End Sub

Private Sub AnalyzeClientMessage(ByVal MessageText As String)
If InStr(MessageText, ProjectListRequest) Then
SendProjectList()
ElseIf InStr(MessageText, ExitRequest) Then
Console.WriteLine("SERVER>Exit command received. Closing
connection.")
Else
Console.WriteLine("SERVER>Message not understood.")
Console.WriteLine("SERVER>Received: " & MessageText &
ControlChars.CrLf)
End If

End Sub

Private Sub SendProjectList()
Console.WriteLine("SERVER>Project List was requested")
Dim sprojectlist As String = db.GetProjectList
sendMessage("RESPONSE:pROJECT_LIST:" & ControlChars.CrLf &
sprojectlist)
End Sub

Public Sub sendMessage(ByVal MessageText As String)
Try
If tcpSocket.Connected Then
Dim SendBytes(1024) As Byte
SendBytes = Encoding.ASCII.GetBytes(MessageText)
tcpSocket.Send(SendBytes, SendBytes.Length,
SocketFlags.None)
End If
Catch e As System.Net.Sockets.SocketException
MessageBox.Show(e.Message, "Connection Error", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Console.WriteLine("SERVER>: " & MessageText)
End Sub
End Class


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An object from this class is initialized in a form for now, and the server
is immediately started.

The vb6 winsock control is initialized as in a menu function follows:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Private Sub mnuInformation_ProjListUpdate_Click()
'connect to server and retrieve project list

With frmPopUp.axWinsockClient
.RemoteHost = "192.168.1.49"
.RemotePort = CLng(9900)
Dim temp As Integer
temp = ServicePointManager.DefaultConnectionLimit
.Connect
Select Case axWinsockClient.State
Case 6
Debug.Print ("connecting....")
Case 7
Debug.Print ("connected to " & .RemoteHostIP & ":" &
..RemotePort)
End Select
If axWinsockClient.State = 7 Then .SendData ("REQUEST:pROJECT_LIST")
.Close
End With

End Sub

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Can anyone help me with this?

thanx,

Dmitry
 
D

Dmitry Akselrod

Hello everyone,

I finally solved my own problem. I will explain my solution in case someone
is experiencing similar issues.

1. my vb6 application uses some API calls to display a systray icon. Most
of the code is there. while I do not fully understand, the API calls are
somehow preventing the successful connection signal from reaching the
winsock control. I am guessing event messages are being rerouted to one of
the other forms.

2. since most of the tcplistener implementations, including my own, use
either a timer or a thread that sleeps after checking for a connection, you
have to be more careful with commands in vb6. For example, if you use the
SendData command to send that, you have to be sure that the tcplister has
time to receive it, before you issue the .close command from vb6 to close
the connection. you can issue the senddata command, then use the
sendcomplete event to close the connection.

it just takes a little more care to get these two to work together, but
they work quite well.

dmitry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top