MESockets.dll
Namespace: MacyEnt.sockets.MESkt
Unicode and ANSI Considerations
The distribution consists of the DLL, a test application and project, and this file. To test the class when you have unzipped everything into an application folder, run two instances of the test application. Define one as a server by entering a port number (i.e. 4000) and pressing the Start As Server button. Define the other as the client by entering the same port number and the name of your workstation (localhost in some cases) in the Client’s Server’s Name field and press the Start As Client button. Enter data into the client’s Data field. Press the server’s Receive button. Press the client’s Send button. The data should show up in the server’s data field. You can now send data back and forth remembering that a Send requires a Receive by the partner. If this does not work, an error will show up in the error text window. This is possibly due to firewall protection.
Files in this distribution:
· MESkt.sln – Visual Studio Solution with test form
· MESkt.suo
· Documentation\MESocket.chm – Compiled HTML of this file.
· MESkt_Test\AssemblyInfo.vb – MESkt_Test is the test project
· MESkt_Test\Form1.vb
· MESkt_Test\MESkt_Test.vbproj
· MESkt_Test\MESkt_Test.vbproj.user
· MESkt_Test\bin\ckeckTrialClass.dll – Used to track use of trial version
· MESkt_Test\bin\MESockets.dll – The ME Socket DLL.
· MESkt_Test\bin\sktTrial.me – Required by the trial version. Should exist in folder from where application is run.
· MESkt_Test\bin\socketTest.exe – The test application. Run this EXE.
An instance of this class provides
Implementation is in one class. (The trial version requires an additional data file.) Socket use is simplified by providing methods to setup as server or client, read, write, and close. Socket calls such as the Listen, Accept, and Connect are hidden from the user as is port handling. While socket protocol is not complicated and the use of the Microsoft socket component simplifies sockets, using the socket classes as provided still requires implementation of timeouts and code to handle the concatenation or parsing of received data to break an input stream into discreet messages. This is also handled by the MESockets component.
This implementation assumes, but does not require, 2-way application communication where a received message is acknowledged before the next is sent. Socket protocol buffers received data and returns ALL available data to the caller in response to a receive call. This can be more than a single message if messages are not acknowledged and sent w/o a response. Or the received data can be less than a complete message due to buffer size limitations or partial message receipt. Since message application acknowledgement is specified as part of application design, this implementation will return a complete message and only a complete message. Transparent to the user, this class includes a length header at the front of the message if the hsend method is used.
Header: <0>length<255>
as ANSII bytes where length is the ASCII representation. The send method sends without a header. This will work for messages shorter than the TCPIP buffer, which is usually between 1000 and 2000 bytes long.
Testing can be done by running the socketTest.exe two times, once as the client and once as the server. The solution can be run in visual studio as well.
During testing, the Start as Server button may cause an error. This is usually due to not gracefully terminating previous testing or setup. Try clicking the button a second time.
From Control Panel, select the Windows Firewall program to run. The following screen will appear. For security reasons, the On radio button should be selected. But this requires that the port being used in an application’s socket program must be listed here as an exception.

Select the exceptions tab and the following screen appears. Click the Add Port button to add a socket exception – in this case, testSockets was was added.

Editing the testSockets exception and adding it as a port both show the following screen:

By pressing the Change Scope button, a list of acceptable users can be specified for the port.

For testing purposes, enter 127.0.0.1 which is the default address for a standalone workstation. Note that the /255.255.255.255 will be added by the firewall logic.
When integrating across a number of different environments, one of the platforms may use only the Ansi character set and NOT the 16-bit Unicode character set now being used on the Microsoft platform. The VB BSTR type is Unicode by default. VB applications written will usually be based upon Unicode unless special steps are taken to code in Ansi. When input from or output to Ansi based systems such as the DEC environment, care must be taken to assure that Ansi environments don’t see Unicode, and that Unicode environments don’t get passed Ansi unexpectedly. Conversions must be done between the environments. Problems can arise when ANSI strings are read into Unicode strings without the proper Encoding being done.
To accommodate connections with “ANSI” systems, the communication is done through byte arrays so that Unicode characterization doesn’t cause problems. However, the using application must still know whether or not communicated arrays are ANSI or Unicode. For example, the application must use the Encoding Methods to convert strings to ANSI character strings prior to sending to ANSI systems such as a VAX.
An easy way to define a module that will receive from or send to both Unicode and ANSI systems is to always convert strings to ANSI arrays prior to sending. The receiving application must them convert them back to Unicode if Unicode is required on the receiving platform. As long as Unicode is NOT required, for example communication of Japanese characters, then this design is not a problem.
Dim mobjSkt As New MACYENT.Sockets.MESkt()
ConnectionActive – True if object is connected to a partner, else False.
Sub serverSetup(ByVal port As Integer)
Sub clientSetup(ByVal serverName As String, _
ByVal port As Integer)
Sub send(ByRef txtSend( ) As Byte, _
ByVal byteLength As Long, _
ByVal timeoutMS As Long)
Sub hsend(ByRef txtSend( ) As Byte, _
ByVal byteLength As Long, _
ByVal timeoutMS As Long)
Sub receive(ByRef bytesReceived As Long, _
ByVal bytesAvailable As Long, _
ByRef txtReceived( ) As Byte, _
ByVal timeout As Long)
Sub closeConnection( ByVal closeType as Byte )
If desired, use send for short messages containing character data. The hsend method may be used for any message.
|
|
Port |
Socket port number. For example, 1030. Standard Internet port is 80. |
|
|
timeout |
Time in seconds to listen before timing out. Maximum value is 86399 seconds (24 hours minus 1 second). |
|
|
closeType |
Clients always close with a closeType=1. A server will use closeType=1 until an error occurs. Then the server should use closeType=2 to close the Listening port and start over. |
sktLostConnection = vbObjectError + 512 + 1
sktNoSocket = vbObjectError + 512 + 2
sktSendTimeout = vbObjectError + 512 + 3
sktRecvTimeout = vbObjectError + 512 + 4
sktZeroLength = vbObjectError + 512 + 5
sktInvalidClose = vbObjectError + 512 + 6
sktInterrupted = vbObjectError + 512 + 7
SocketException
ArgumentNullException
NullReferenceException
Dim mobjSkt As New MACYENT.Sockets.MESkt()
Dim mobjEncoder As Encoding()
Dim lc As Integer = MACYENT.Sockets.MESkt.sktLostConnection
Dim ns As Integer = MACYENT.Sockets.MESkt.sktNoSocket
Dim st As Integer = MACYENT.Sockets.MESkt.sktSendTimeout
Dim rt As Integer = MACYENT.Sockets.MESkt.sktRecvTimeout
Dim zl As Integer = MACYENT.Sockets.MESkt.sktZeroLength
Dim ic As Integer = MACYENT.Sockets.MESkt.sktInvalidClose
Try
' Define self as Server and wait for connection from client
mobjSkt.serverSetup(4050)
' Receive a message
mobjSkt.receive(llngByteReceived, 100, lbytSktArray, 10000)
dataTextBox.Text = Encoding.ASCII.GetString(lbytSktArray)
lenTextBox.Text = llngByteReceived
' Send a short message (in this case an ACK)
lstrDataMessage = “ACK”
lbytSktArray = Encoding.ASCII.GetBytes(lstrDataMessage)
mobjSkt.send(lbytSktArray, UBound(lbytSktArray) + 1, 10000)
... Define lstrLongMessage
' Send a long message
lbytSktArray = Encoding.ASCII.GetBytes(lstrLongMessage)
mobjSkt.hsend(lbytSktArray, UBound(lbytSktArray) + 1, 10000)
' Close this conversation’s port
mobjSkt.closeConnection(1)
Catch excp As Exception
errTextBox.Text = excp.ToString
mobjSkt.closeConnection(1)
' Close the connection listening port
mobjSkt.closeConnection(2)
End Try