Title: Socket Programming in C
1Socket Programming in C
- The content of this presentation is based on the
following
- http//www.codeguru.com/csharp/csharp/cs_network/s
ockets/print.php/c7695
- http//www.codeguru.com/Csharp/Csharp/cs_network/s
ockets/article.php/c8781/
2Asynchronous Socket Programming in C
- Client-Server Example with Multiple Simultaneous
Clients
- How to create a Socket-based client/server
application
- Allow two-way asynchronous communication between
a server and multiple client applications
- Asynchronous methods
- Server application does not use threads to
communicate to multiple clients
- Internally the asynchronous communication
mechanism uses threads at the OS level
3Asynchronous Socket Programming in C
- The Difference between Synchronous and
Asynchronous Communication in Network Programming
- Synchronous communication
- The server is waiting to receive data from one
client at a time
- Not applicable
- Asynchronous communication
- The server can process connection requests while
the server is listening or receiving data from a
client
- Separate thread (at the OS level) listens on the
socket and will invoke a callback function
4Asynchronous Socket Programming in C
- The Difference between Synchronous and
Asynchronous Communication in Network Programming
- C and .NET frameworks do asynchronous
communications without introducing the complexity
of threading
5Asynchronous Socket Programming in C
- Socket Class
- The Socket class (System.Net.Sockets.Socket)
- Support both synchronous and asynchronous methods
for synchronous or asynchronous communication
- Naming convention
- Asynchronous method names
- Prefixing the words "Begin" or "End" to the name
of the synchronous methods.
6Socket Server Implementation
7Example
- Two classes
- The Socket Server
- The Socket Client
8Socket Server Implementation
- Socket Server application ? SocketServer class ?
SocketServer.cs
- members
- Main Socket object ? m_mainSocket
- Listening for the clients
- Transfers the client processing to a worker
Socket.
- Then continues listening
- Array of worker Socket objects ? m_workerSocket
9Socket Server Implementation
- Socket Server application ? SocketServer class ?
SocketServer.cs
- Methods
- BeginAccept()
- public IAsyncResult BeginAccept(
- AsyncCallback callback, // (1) Function to
call when a client
// is connected
- object state // (2) State
object to preserve socket
// info
- )
- BeginReceive()
10Socket Server Implementation
Here we complete/end the BeginAccept()
asynchronous call by calling EndAccept() - which
returns the reference to a new Socket object
- public void OnClientConnect(IAsyncResult asyn)
-
- try
-
- m_workerSocketm_clientCount
m_mainSocket.EndAccept (asyn)
- WaitForData(m_workerSocketm_clientCount)
- m_clientCount
- String str String.Format("Client 0
connected", m_clientCount)
- textBoxMsg.Text str
- m_mainSocket.BeginAccept(new AsyncCallback
( OnClientConnect ),null)
-
- catch(ObjectDisposedException)
- System.Diagnostics.Debugger.Log(0,"1","\n
OnClientConnectionSocket has been closed\n")
- catch(SocketException se) MessageBox.Show (
se.Message )
11Socket Server Implementation
Let the worker Socket do the further processing
for the just connected client
- public void OnClientConnect(IAsyncResult asyn)
-
- try
-
- m_workerSocketm_clientCount
m_mainSocket.EndAccept (asyn)
- WaitForData(m_workerSocketm_clientCount)
- m_clientCount
- String str String.Format("Client 0
connected", m_clientCount)
- textBoxMsg.Text str
- m_mainSocket.BeginAccept(new AsyncCallback
( OnClientConnect ),null)
-
- catch(ObjectDisposedException)
- System.Diagnostics.Debugger.Log(0,"1","\n
OnClientConnectionSocket has been closed\n")
- catch(SocketException se) MessageBox.Show (
se.Message )
12Socket Server Implementation
Now increment the client count
- public void OnClientConnect(IAsyncResult asyn)
-
- try
-
- m_workerSocketm_clientCount
m_mainSocket.EndAccept (asyn)
- WaitForData(m_workerSocketm_clientCount)
- m_clientCount
- String str String.Format("Client 0
connected", m_clientCount)
- textBoxMsg.Text str
- m_mainSocket.BeginAccept(new AsyncCallback
( OnClientConnect ),null)
-
- catch(ObjectDisposedException)
- System.Diagnostics.Debugger.Log(0,"1","\n
OnClientConnectionSocket has been closed\n")
- catch(SocketException se) MessageBox.Show (
se.Message )
13Socket Server Implementation
Display this client connection as a status
message on the GUI
- public void OnClientConnect(IAsyncResult asyn)
-
- try
-
- m_workerSocketm_clientCount
m_mainSocket.EndAccept (asyn)
- WaitForData(m_workerSocketm_clientCount)
- m_clientCount
- String str String.Format("Client 0
connected", m_clientCount)
- textBoxMsg.Text str
- m_mainSocket.BeginAccept(new AsyncCallback
( OnClientConnect ),null)
-
- catch(ObjectDisposedException)
- System.Diagnostics.Debugger.Log(0,"1","\n
OnClientConnectionSocket has been closed\n")
- catch(SocketException se) MessageBox.Show (
se.Message )
14Socket Server Implementation
Since the main Socket is now free, it can go back
and wait for other clients who are attempting to
connect
- public void OnClientConnect(IAsyncResult asyn)
-
- try
-
- m_workerSocketm_clientCount
m_mainSocket.EndAccept (asyn)
- WaitForData(m_workerSocketm_clientCount)
- m_clientCount
- String str String.Format("Client 0
connected", m_clientCount)
- textBoxMsg.Text str
- m_mainSocket.BeginAccept(new AsyncCallback
( OnClientConnect ),null)
-
- catch(ObjectDisposedException)
- System.Diagnostics.Debugger.Log(0,"1","\n
OnClientConnectionSocket has been closed\n")
- catch(SocketException se) MessageBox.Show (
se.Message )
15Socket Server Implementation
- OnClientConnect()
- Call the EndAccept() method on the m_mainSocket
member object
- Will return a reference to another socket object
- Set this object reference to one of the members
of the array of Socket object references you have
(m_workerSocket)
- Increment the client counter
- The main Socket (m_mainSocket) is free
- Call its BeginAccept() method
- To start waiting for connection requests from
other clients.
- Worker socket
- Receive the data from the client
- Call BeginReceive() and EndReceive()
- The server uses the specific worker socket
objects to send data to each client.
16Socket Client Implementation
17Socket Client Implementation
- The Socket Client application ? SocketClient
class ? SocketClient.cs
- Server Main Socket, Array of worker Sockets
- Client
- Single Socket object ? m_clientSocket
- Methods
- Connect()
- Synchronous method that connects to a listening
server
- To succeed we need an active and listening
server at the specified IP and Port number
- BeginReceive()
18Socket Client Implementation
- The Socket Client application ? SocketClient
class ? SocketClient.cs
- Server Main Socket, Array of worker Sockets
- Client
- Single Socket object ? m_clientSocket
- Methods
- Connect()
- BeginReceive()
- Connection should be established first
- Asynchronous function
- Client can send any data to the server while
waiting for data from the server.
- Wait for any socket write activity by the server
19Socket Client Implementation
- Limitations/Possible Improvements
- Up to 10 simultaneous clients are supported
- You can easily modify and support unlimited
number of clients by using a HashTable instead of
an array.
- Server messages are broadcasted to all the
connected clients
- Needs to be modified to send messages to specific
clients by using the Socket object pertaining to
that particular client.
- No action taken for disconnected clients
- Client count needs to be decremented
- Release resources new clients
20Socket example with advanced features (single
server/multiple clients)
- Features Added
- Unlimited number of clients
- Link clients to their messages
- Reply to specific clients
- Identify disconnected clients
- List connected clients at any given time
- Release resources for disconnected clients
21Socket Server
22Socket Client
23Unlimited Number of Clients
- Using an arrayList instead of an array of Socket
objects to store the references to the worker
sockets.
- private System.Collections.ArrayList
- m_workerSocketList new System.Collections.ArrayL
ist()
- // Total number of clients connected at any time
- // May generate an overflow
- private int m_clientCount 0
24How to Find Which Client Sent a Particular Message
- Assign each client a serially incremented number
once they connected to the server
25How to Find Which Client Sent a Particular Message
- public void OnClientConnect(IAsyncResult asyn)
- try
- Socket workerSocket m_mainSocket.EndAccept
(asyn)
- m_clientCount
-
- m_workerSocketList.Add(workerSocket)
-
- WaitForData(workerSocket, m_clientCount)
26How to Find Which Client Sent a Particular Message
- //Asynchronous call to receive the data from the
client
- public void WaitForData(System.Net.Sockets.Socket
soc, int clientNumber)
- try
- if( pfnWorkerCallBack null )
-
- // Specify the callback function that is
to be invoked when
- // there is any write activity by the
connected client
- pfnWorkerCallBack new AsyncCallback
(OnDataReceived)
-
- SocketPacket theSocPkt new SocketPacket
(soc, clientNumber)
- // Start receiving any data written by the
connected client asynchronously
- soc.BeginReceive (theSocPkt.dataBuffer, 0,
theSocPkt.dataBuffer.Length,
- SocketFlags.None, pfnWorkerCallBack,
theSocPkt)
- //........
27How to Find Which Client Sent a Particular Message
- // definition of the SocketPacket class.
- public class SocketPacket
-
- // Constructor that takes a Socket and a
client number
- public SocketPacket(System.Net.Sockets.Socket
socket, int clientNumber)
-
- m_currentSocket socket
- m_clientNumber clientNumber
-
- public System.Net.Sockets.Socket
m_currentSocket
- public int m_clientNumber
- // Buffer to store the data sent by the
client
- public byte dataBuffer new byte1024
28How to Reply or Send Messages to Specific Clients
- SocketPacket object
- Contains the reference to a particular worker
socket
- Use SocketPacket object to reply to the client
- Or
- Use the worker socket object stored in the
ArrayList to send any message to any particular
client.
29How to Find when a Particular Client is
Disconnected
- A client is disconnected
- Use the last called OnDataReceived() function
- If there is no data sent by the cient
- This function will throw a SocketException
- Error code 10054 ? client disconnected
30How to Find when a Particular Client is
Disconnected
- Here again, the SocketPacket object will give you
the index number of the client that was
disconnected.
- catch(SocketException se)
-
- if(se.ErrorCode 10054) // Error code for
Connection reset by peer
-
- string msg "Client "socketData.m_clientNumber"
Disconnected" "\n"
- richTextBoxReceivedMsg.AppendText(msg)
- // Remove the reference to the worker socket of
the closed client
- m_workerSocketListsocketData.m_clientNumber - 1
null
- UpdateClientList()
-
- else MessageBox.Show (se.Message )
-
31How to Get the List of All Connected Clients at
Any Given Time
- A dynamic list is displayed on the server GUI
that will be updated (see the UpdateClientList()
function) whenever a client is connected or
disconnected.
32Are Variables Safe in AsyncCallback Methods?
- Asynchronous programming
- Uses asynchronous delegates
- Using asynchronous calls
- Threads used behind the scenes to achieve the
asynchronous nature of these calls.
- Asynchronous functions
- OnClientConnect() and OnDataReceived()
- Called by threads other than the main GUI thread
33What About Thread Synchronization?
- Threads
- 1) is the main GUI thread that starts when you
start the Server application. The thread labeled
- 2) starts whenever any client tries to connect to
the socket. The thread labeled
- 3) spawns when there is any write activity by any
one of the connected clients.
34Threading issues to consider
- 1. Shared variables
- m_clientCount and m_workerSocketList
- if modified inside the shared code
- Must be protected by synchronization structures
from modification by multiple threads at the same
time
- m_clientCount
- Incremented by using the static method within the
Interlocked class
- m_workerSocketList
- Create a Synchronized ArrayList
- 2. Modifying the GUI
35Threading issues to consider
- 1. Shared variables
- Increment the client count in a thread safe
manner
- Interlocked.Increment(ref m_clientCount)
- Create a Synchronized ArrayList
- private System.Collections.ArrayList
m_workerSocketList ArrayList.Synchronized(new
System.Collections.ArrayList())
36Threading issues to consider
- 1. Shared variables
- 2. Modifying the GUI
- The main GUI thread owns the GUI controls
- Not recommended to access or modify any of the
GUI controls by threads other than the main thread
37Threading issues to consider
- 2. Modifying the GUI
- // This method could be called by either the main
thread or any of the worker threads
- private void AppendToRichEditControl(string msg)
-
- // Check to see if this method is called from
a thread other than the one created the control
- if (InvokeRequired)
-
- //We cannot update the GUI on this thread.
- //All GUI controls are to be updated by the main
(GUI) thread.
- //Hence, we will use the invoke method on the
control that will be called when the //main
thread is free do UI update on UI thread
- object pList msg
- richTextBoxReceivedMsg.BeginInvoke(new
UpdateRichEditCallback( OnUpdateRichEdit),
pList)
- else
38Threading issues to consider
- 2. Modifying the GUI
- // This method could be called by either the main
thread or any of the worker threads
- private void AppendToRichEditControl(string msg)
-
- // Check to see if this method is called from
a thread
- // other than the one created the control
- if (InvokeRequired)
-
-
-
- else
-
- // This is the main thread which created this
control, hence update it directly
- OnUpdateRichEdit(msg)
-
39Threading issues to consider
- 2. Modifying the GUI
- // This UpdateRichEdit will be run back on the UI
thread
- // (using System.EventHandler signature so we
don't
- // need to define a new delegate type here)
- private void OnUpdateRichEdit(string msg)
-
- richTextBoxReceivedMsg.AppendText(msg)
40Final Comments
- C and network programming
- The C language provides you with all the tools
necessary to quickly develop networked
applications.
- Compared to C and Java
- C have a richer set of programming APIs
- Eliminates most of the complexities previously
associated with network programming