Introduction
This article contains synoptical analysis of multi socket programming for client side. Doing coding for client side in socket programming & doing coding it in muliti socket programming; is different.
Background
Multi socket programming is few steps ahead in socket programming as one client is connected to one server who is listing at particular port in traditional socket programming whereas one client get connected to two servers at different ports on same machine or on different machines in multi socket programming.
This analysis is done on Microsoft Visual Studio 2003 and .Net Framework 1.1. This analysis is purely meant for intermediate and/or expert professionals of Microsoft Visual Studio 2003 and .Net Framework 1.1. If you have firewall on your system make sure it won't disallow connection.
In this report I have added order analysis and flow analysis of execution for these applications; this will definitely enhance your gained knowledge. It is better to understand the order and flow of execution for a sound professional in software engineering. If you think that you are expert in software development you can directly switch your study to these (order analysis and flow analysis).
Some professionals may find the scope of explanation from technical point of view but as a sound understanding of these applications (i.e. server and client) it is sufficient. If I write whole things, this will put me on long journey to complete and make puzzle and confuse you too. Do remember one thing that there should be limit of explanation depending on requirement and that limit is achieved here for our requirement and purpose. Even if you want to explore more you can proceed; I Welcome.
I have included at the end complete references (i.e. their definition, overview, public constructors, public methods, protected methods, properties etc.) of TcpListener Class, TcpClient Class. Make sure that you should read them as I have used TcpListener Class and TcpClient Class for multi socket programming.
Using the code
Multiple Sockets Programming
What is multi socket programming? Technically it is way of socket programming in which two sockets connecting to either two different servers or same server. What exactly multi socket programming is? For that understand what traditional socket programming is, simultaneously with multi socket programming.
Socket or sockets are logical connections that are created to connect the computers to each others. A port number and a host IP Address/Host name is required to create a socket. Thread or threads are that pieces of a process or program that are assigned some resources, such as file, I/O, and so forth and are able to run individually. Multithreading means many threads of a process can be run on a single processor assigning them an equal time slice and priority, each feeling that it is the only process running.
We implement socket programming in case whenever there is need to make a communication between two machines (here machine stands for computer system), in which one machine act as server and while other as client.
The role of server is to keep listening to the incoming connection's request(s) at particular port. Client sends a request to server to establish a communication through ipaddress of server (or name of server) and port no at which server is listening. Now what happen in multi socket programming is that a client sends request of connection to two or more servers those are listening at their respective port in consideration.
It is up to the server(s) to accept connection request (send by client) or to reject it. If server(s) accepts the connection a virtual pipeline (technically a socket) is created for the communication of messages between server and client to and fro. During the time when a client has active connection to server(s) it can send and receive data from server(s), and then close the connection. These connections are expensive in terms of resources utilized. Server (s) can also restricted to limited number of clients to connect. Again I am repeating that it is server/client architecture because one the computer will act as a server (which is responding to client messages) whiles all other computer behaves as clients (that only send request to server to establish a communication).
A beautiful complexity exhibits by multi socket programming is that a server(s) sends data to any connected client or to all connected clients (that is broadcasting) is to be read by client(s) but how the client(s) came to know which server has send this data. Other difficulty is when either side sends data to other side is supposed to read it but how the other side came to know that any data has arrived. I will explain these issues in detail in later part of this document so stick to it.
Coding Analysis- The Client
Here I am exploring simple client for better understanding. This client connects to two different servers and start communicating with them. The total numbers of functions which are used in this are listed as under:
i) Form2_Load()
ii) DoReadOne()
iii) DoReadSec()
iv) DisplayText()
v) btnSendFirst_Click()
vi) SendForFirst()
vii) btnSendSecond_Click()
viii) SendForSecond()
ix) btnAllServer_Click()
x) MarkAsDisconnected()
Same important thing I write in my every document is before proceeding that all these functions are listed on structural basis. If anyone is trying to find syntax errors (e.g. no of arguments in Form2_Load event) please forgive me. Thanks to God.
Now one more thing following are the imports files for this project's class
Imports System.Net
Imports System.Net.Sockets
Both these files are important as .net provide enrich set of functions through these classes.
Private marDataOne(1024) As Byte
Private mobjClient, mobjClientSec As TcpClient
Private Delegate Sub callDisplayText(ByVal t As String)
Elaborating Function
The full code is as under
"vb.net">
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Try
mobjClient = New TcpClient("192.168.1.8", 1007)
DisplayText("Connected To Server At Port: 1007" & "~" & "DoReadOne")
mobjClient.GetStream.BeginRead(marDataOne, 0, 1024, AddressOf DoReadOne, Nothing)
mobjClientSec = New TcpClient("192.168.1.8", 2007)
DisplayText("Connected To Server At Port: 2007" & "~" & "DoReadSec")
mobjClientSec.GetStream.BeginRead(marDataOne, 0, 1024, AddressOf DoReadSec, Nothing)
Catch ex As Exception
Dim strErrMsg As String
strErrMsg = ex.Message.ToString
If strErrMsg = "No connection could be made because the target machine actively refused it" Then
strErrMsg = "Ask Administrator To Start The Server As " & vbCr & vbCr & "No Connection Could Be Made Because The Target Machine Actively Refused It"
MessageBox.Show(strErrMsg, "Connection Error")
Else
strErrMsg = "Error: While Connecting To Desired Machine For Communication"
MessageBox.Show(strErrMsg, "Connection Error")
End If
Application.Exit()
Me.Close()
End Try
End Sub
"TEXT-ALIGN: justify">In this function objects of TcpClient
Now I am checking asynchronously for data to receive from either server. This is done with the help of BeginRead() function which is available in getstream of TcpClient object. This BeginRead function is called twice first by
Elaborating Function
"TEXT-ALIGN: justify">DoReadOne() function accepts an object of IAsyncResult interface. This object is responsible for receiving no of bytes from network stream. If number of bytes received are less than 1 it means that particular socket is now closed (obviously it means that particular server is closed) so call
Private Sub DoReadOne(ByVal ar As IAsyncResult)
Try
Dim strMsg As String
Dim intCount As Integer
Dim tempObj As Object
intCount = mobjClient.GetStream.EndRead(ar)
If intCount < 1 Then
MarkAsDisconnected()
Exit Sub
End If
strMsg = System.Text.ASCIIEncoding.ASCII.GetString(marDataOne, 0, intCount)
strMsg = strMsg & "~" & "DoReadOne"
Dim obj As New callDisplayText(AddressOf DisplayText)
obj.BeginInvoke(strMsg, Nothing, Nothing)
mobjClient.GetStream.BeginRead(marDataOne, 0, 1024, AddressOf DoReadOne, Nothing)
Catch e As Exception
MarkAsDisconnected()
End Try
End Sub
"TEXT-ALIGN: justify">Look at this code "System.Text.ASCIIEncoding.ASCII.GetString(marDataOne, 0, intCount)
TEXT-ALIGN: justify">GetString function accepts three arguments first is the byte array, second is index, third is number of bytes to read.
TEXT-ALIGN: justify">BeginRead() function accepts five parameters
TEXT-ALIGN: justify">First: byte array
TEXT-ALIGN: justify">Second: offset
TEXT-ALIGN: justify">Third: size i.e. number of bytes to be read
TEXT-ALIGN: justify">Fourth: a callback delegate
TEXT-ALIGN: justify">Fifth: object
TEXT-ALIGN: justify">Here this last i.e. fifth parameter in BeginRead() function is set to nothing but this can be used to retrieve additional information of socket. After executing BeginRead() function I again invoke BeginRead() function just to make sure that whenever there is data available to socket it can be retrieved instantly.
Elaborating Function 'DoReadSec()'
Whole thing is same in this function as they are in DoReadOne() except it is meant for second TcpClient class's object mobjClientSec() that is to communicate with second server.
Elaborating Function 'DisplayText ()'
This function is used to show data on two different list box depending upon from which server it is coming. That is if it is coming from first server this will show data on first list box else in second. This categorization is done with the help of incoming data as a parameter. As this data is concatenated with identifier "DoReadOne" and "DoReadSec" in DoReadOne() and in DoReadSec() function respectively.
'function to display message in text box
Private Sub DisplayText(ByVal t As String)
Dim strMsg As String
Dim arrMsg(2) As String
arrMsg = t.Split("~")
strMsg = arrMsg(0)
If arrMsg(1) = "DoReadOne" Then
lstBoxOne.Items.Add(strMsg)
Else
lstBoxSec.Items.Add(strMsg)
End If
End Sub
Elaborating Function 'btnSendFirst_Click()'
TEXT-ALIGN: justify">This block of code is invoked whenever user click ToFirst button from GUI. This code take data from text box and call sendForFirst() function to send data to First server. After sending data to server text box is cleared. The complete code is as under
'code to send message to first server
Private Sub btnSendFirst_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSendFirst.Click
Try
'validation to enter some text to send
If txtSend.Text = "
" Then
MessageBox.Show("Please Enter Some Text In Message Box Before Sending")
Exit Sub
End If
'calling send function to send data to server
SendForFirst(txtSend.Text)
txtSend.Text = ""
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Elaborating Function 'SendForFirst ()'
TEXT-ALIGN: justify">Send function is responsible to send data to network stream to first server. This is achieved with the help of object of IO.StreamWriter class. This function gets invoked whenever ToFirst button is clicked. Use of flush() is to clears all buffers for current writer. The complete code goes like this
'function to send data to first server
Private Sub SendForFirst(ByVal t As String)
Try
Dim w As New IO.StreamWriter(mobjClient.GetStream)
w.Write(t)
w.Flush()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Elaborating Function 'btnSendSecond_Click()'
Same conceptual theory as btnSendFirst_Click() except it is meant for sending data to second server.
Elaborating Function 'SendForSecond ()'
Same conceptual theory as SendForFirst except it is meant for sending data to second server.
Elaborating Function 'btnAllServer_Click()'
This function is invoked wherever client click on ToAllServer button. This is used to send data of text box to both the servers. The code is self explanatory as it invoke sendForFirst() & sendForSecond() function to send data to both servers.
'code to send message to all servers
Private Sub btnAllServer_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAllServer.Click
Try
'validation to enter some text to send
If txtSend.Text = "
" Then
MessageBox.Show("Please Enter Some Text In Message Box Before Sending")
Exit Sub
End If
'calling send function to send data to all servers
SendForFirst(txtSend.Text)
SendForSecond(txtSend.Text)
txtSend.Text = ""
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Elaborating Function 'MarkAsDisconnected()'
TEXT-ALIGN: justify">This function is simply invoked in any case when there is a need to exit the application uninterruptedly. The complete code goes like this
'function to mark connection as disconnected
Private Sub MarkAsDisconnected()
Try
'declare string variable for displaying error message
Dim strErrMsg As String
'concatenating error string msg
strErrMsg = "
Unable To Communicate With Server, Server Is Not Responding"
MessageBox.Show(strErrMsg, "Connection Error")
'exiting from application properly
Me.Close()
Application.Exit()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Order Execution Analysis� Client
As sound professional of software engineering one should know the order of execution of application. One should know how function is invoked how they call each other and how whole process came to end for a particular process in application. That is why I am doing with Client application.
Following are the categories that I will explore in terms of their order of execution for client
i) when client starts
ii) when message send to first server
iii) when message send to second server
iv) when message send to all server
v) when message receive from first server
vi) when message receive from second server
vii) when first server close
viii) when second server close
ix) when client close
i) When client starts
form_load() calls DoReadSec() and DoReadOne() asynchronously. which in turn DisplayText function is called by both.
ii) when message send to first server
This called sendForFirst() function.
iii) when message send to second server
This called sendForSecond() function.
iv) when message send to all server
This called sendForFirst() & sendForSecond() function.
v) when message receive from first server
This calls first for DoReadOne() and then DisplayText() function.
vi) when message receive from second server
This calls first for DoReadSec() and then DisplayText() function.
vii) when first server close
This call DoReadOne() which in turn call DoReadOne() and finally MarkAsDisconnected() functions.
vii) when second server close
This call DoReadSec() which in turn call DoReadSec() and finally MarkAsDisconnected() functions.
vii) when client close
Nothing happens.