network programming .pdf
TRANSCRIPT
-
Network Programming
Socket Programming in .NET
-
Basic Outline
An Overview of Sockets
Working with Sockets in .NET
Asynchronous Programming
Socket Permissions
-
Basic Outline
An Overview of Sockets
Working with Sockets in .NET
Asynchronous Programming
Socket Permissions
-
An Overview of Sockets Definition
A socket is one end of a two-way communication link between two programs running on a network
Connection can be local or remote Socket implementation provides the encapsulation of the network and
transport level protocols
A socket, being a resource, is also represented by a descriptor Socket Types
Stream Sockets Connection-orientated Consists of a stream of bytes that can be bidirectional Guarantees error correction, handles delivery and preserves data
sequence and guarantees non-duplicated data
High level of quality using TCP Suitable for large amounts of data Large overhead makes it bulky for small amounts of data Path is formed before communication starts (ensures that both
parties are active and participating)
Uses data packets and relies on TCP for delivery of packets Datagram Sockets Raw Sockets
Sockets and Ports
-
An Overview of Sockets
Definition Socket Types
Stream Sockets Datagram Sockets
Also called connectionless sockets (no explicit connections are established)
Message is just sent without knowledge of the receiver Uses UDP to pass data from client to server Message size limitations and no guarantee of delivery Used when overhead of stream sockets does not warrant the
message (i.e. when the message is too small/insignificant)
Raw Sockets
Sockets and Ports
-
An Overview of Sockets Definition Socket Types
Stream Sockets Datagram Sockets Raw Sockets
A socket that takes packets, bypassing the TCP and UDP layers in the TCP/IP stack and sends them directly to the application
Purpose is to bypass the mechanism by which the computer handles TCP/IP.
Provides a custom implementation of the TCP/IP stack It is more efficient than going through the clients main stack No processing on the packet (i.e. raw) The receiving application has to handle the data
appropriately and deal with actions such as stripping off headers and parsing
Used for custom low-level protocol applications Sockets and Ports
-
An Overview of Sockets Definition Socket Types
Stream Sockets Datagram Sockets Raw Sockets
Sockets and Ports A port is defined to solve the problem of communicating with
multiple applications simultaneously; it basically expands the notion of an IP address
A computer can identify an arriving packet by the port number it is arriving through
Port numbers are established when connections are made The socket is composed of the IP address of the machine and
the port number used by the TCP application; this is also called an endpoint.
Endpoints are unique across the entire Internet because IP addresses are unique
Certain services have port numbers reserved for them; these are the well-known port numbers (FTP = 21)
-
An Overview of Sockets
Server Client
Port
Connection Request
Normally a client/server application using sockets consists of two different
applications: a client that initiates the connection with the target (server) and the
server, which waits for the connection from the client. For example, on the client side,
the client must know the targets address and the port number. To make the connection request, the client tries to establish the connection with the server.
Server
Client
Port
Port
Start
communication
Port
If everything goes well, provided that the server is running
before the client tries to connect to it, the server accepts
the connection. Upon acceptance, the server application
create a new socket to deal specifically with the connect
client.
The client and the server can now communicate with each
other by reading from and writing to their respective
sockets.
-
Basic Outline
An Overview of Sockets
Working with Sockets in .NET
Asynchronous Programming
Socket Permissions
-
Classes in the System.Net.Sockets
Namespace
Classes Description
MulticastOption Contains IPAddress values used to join and drop multicast groups. Sets IP
address values for joining or leaving an IP multicast group.
NetworkStream Provides the underlying stream of data for network access. It is a high-level
abstraction representing a connection to a TCP/IP communication channel.
TcpClient Provides client connections for TCP network services. Builds on the socket class to provide TCP services at a higher level. TCPClient provides several methods for
sending and receiving data over a network.
TcpListener Listens for connections from TCP network clients. Builds on the low-level Socket
class. Its main purpose is in server applications. This class listens for the incoming
client connections and notifies the application of any connections.
UdpClient Provides User Datagram Protocol (UDP) network services. Implements UDP
services. UDP is a connectionless protocol, therefore a different type of functionality
is required to implement UDP services in .NET
SocketException The exception that is thrown when a socket error occurs. The exception thrown when
an error occurs in a socket.
Socket Implements the Berkeley sockets interface. Provides the basic functionality of a
socket application.
-
System.Net.Sockets.Socket
PropertiesAddressFamily Gets the address family of the Socket. The value is from the
Socket.AddressFamily enumeration.
Available Gets the amount of data that has been received from the network and is
available to be read (returns the amount of available data to read).
Blocking Gets or sets a value that indicates whether the Socket is in blocking mode.
Connected Gets a value that indicates whether a Socket is connected to a remote host as of
the last Send or Receive operation.
LocalEndPoint Gets the local endpoint.
-
System.Net.Sockets.Socket
PropertiesProtocolType Gets the protocol type of the Socket.
RemoteEndPoint Gets the remote endpoint of the socket.
SocketType Gets the type of the Socket.
SupportsIPv4 Returns a Boolean value indicating whether IPv4 support is available
and enabled on the current host.
SupportsIPv6 Returns a Boolean value that indicates whether the Framework
supports IPv6 for certain obsolete Dns members.
-
System.Net.Sockets.Socket
Methods
Method Description
Accept Creates a new Socket for a newly created connection to handle the incoming
connection request.
Bind Associates a Socket with a local endpoint for listening for incoming
connections.
Close Overloaded. Closes the Socket connection and releases all associated
resources.
Connect Overloaded. Establishes a connection to a remote host.
GetSocketOption Overloaded. Returns the value of a Socket option.
IOControl Overloaded. Sets low-level operating modes for the Socket. This method
provides low-level access to the underlying socket instance of the Socket
class.
-
System.Net.Sockets.Socket
Methods
Method Description
Listen Places a Socket in a listening state. This method
is exclusively used to server applications.
Receive Overloaded. Receives data from a bound Socket.
Poll Determines the status of the Socket.
Select Determines the status of one or more sockets.
Send Overloaded. Sends data to a connected Socket.
SetSocketOption Overloaded. Sets a Socket option
Shutdown Disables sends and receives on a Socket.
-
Working with Sockets in .NET
Creating a TCP Stream Socket Application
Building a TCP Server
Building a TCP Client
Managing Exceptions with System.NET
Sockets
Setting and Retrieving Socket Options
-
Building
a TC-
based
Server
Serve
r
Open a Socket
(Socket)
Name the Socket
(Bind)
Listen for incoming Connection
(Listen)
Accept client connection
(Accept)
Send/Receive Data
(Send/Receive)
Close Socket
(Close)
-
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace TestSockets
{
class SocketServer
{
static void Main(string[] args)
{
//establish the local endpoint for the socket
IPHostEntry ipHost = Dns.GetHostEntry("localhost");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 1100);
Establish the local endpoint for the
socket.
Before opening a socket, you need to
establish a local endpoint address.
The local endpoint address is the host
IP Address and the port number that is
going to be used
Note: System.Net & System.Net.Sockets
Returns all network
addresses supported
-
//Create a TCP/IP Socket
Socket sListener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//Bind the Socket to the local endpoint and listen to the
incoming sockets
try
{
sListener.Bind(ipEndPoint);
sListener.Listen(10);
while (true)
{
Console.WriteLine("Waiting for connection on port
{0}.", ipEndPoint);
The Bind method associates a socket with a local
endpoint. You must call Bind before any attempt to call
Listen or Accept.
The maximum pending connections
-
//program is suspended while waiting for an incoming
connection
Socket handler = sListener.Accept();
string data = null;
//We got the client attempting to connect
while (true)
{
byte[] bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0,
bytesRec);
if (data.IndexOf("") > -1)
break;
}//end of while
Accept extracts the first
connection in the queue,
receives the client
connection and creates a
new socket to handle it. The Accept method
blocks the caller thread
until the connection is
present.
Accept may open up multiple sockets. Once the client and server are connected
with each other, you an send and receive using the Send and Receive methods of
the Socket class. The exact protocol definition between the client and server
needs to be clearly defined before sockets may send and receive.
-
//show the data on the console
Console.WriteLine("Text Received: {0}", data);
string theReply = "Thank you for those " + data.Length.ToString() + " characters...";
byte[] msg = Encoding.ASCII.GetBytes(theReply);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}//end of while
Console.WriteLine("press a key");
} //end of try
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
sListener.Close();
}
Console.ReadLine();
}
}
}
-
Working with Sockets in .NET
Creating a TCP Stream Socket Application
Building a TCP Server
Building a TCP Client
Managing Exceptions with System.NET
Sockets
Setting and Retrieving Socket Options
-
Building
a TC-
based
Client
Client
Open a Socket
(Socket)
Connect to Remote Host
(Connect)
Send/Receive Data
(Send/Receive)
Close Socket
(Close)
-
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace TestSocketClient
{
class SocketClient
{
static void Main(string[] args)
{
//Data buffer for incoming data
byte[] bytes = new byte[1024];
//Connect to a remote device
try
{
//Establish the remote endpoint for the socket
IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 1100);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Connect the socket to the remote endpoint
sender.Connect(ipEndPoint);
-
Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString());
string theMessage = "This is a test.";
byte[] msg = Encoding.ASCII.GetBytes(theMessage + "");
//Send the data through the socket
int bytesSent = sender.Send(msg);
//Recieve the response from the remote device
int bytesRec = sender.Receive(bytes);
Console.WriteLine("The Server says : {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
//Release the Socket
sender.Shutdown(SocketShutdown.Both);
sender.Close();
} //end of try
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.ToString());
} //end of catch
Console.ReadLine();
} //end of Main
}
}
-
Constructing a Port Scanner
Scans for open ports (sees who is listening)
Makes a connection with each port specified in the loop
Socket Exceptions have an integer value associated with it
-
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace PortScanner
{
class Program
{
static void Main(string[] args)
{
IPAddress address = IPAddress.Parse("127.0.0.1");
int[] listeningPorts = new int[50];
int count = -1;
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Loop through ports 1 to 1024
for (int i = 1; i
-
//Connect the socket to the remote endpoint
sSocket.Connect(endPoint);
Console.WriteLine("Port {0} is listening.", i.ToString());
++count;
listeningPorts[count] = i;
} //end of try
catch (SocketException ignored)
{
if (ignored.ErrorCode != 10061)
Console.WriteLine(ignored.Message);
} //end of catch
finally
{
if (sSocket.Connected)
{
sSocket.Shutdown(SocketShutdown.Both);
sSocket.Close();
} //end of if
} //end of finally
} //end of for loop
Console.WriteLine("There are {0} ports listening.", count + 1);
for (int j = 0; j
-
Working with Sockets in .NET
Creating a TCP Stream Socket Application
Building a TCP Server
Building a TCP Client
Managing Exceptions with System.NET
Sockets
Setting and Retrieving Socket Options
-
Managing Exceptions with System.Net.Sockets
Socket class generally throws the SocketException
SocketException thrown when
Mismatch or incompatibility in AddressFamily, SocketType or
ProtocolType
Possible places: construct new socket or connect method
-
Socket Exception EnumerationsMember name Description
AccessDenied An attempt was made to access a Socket in a way that is forbidden by its
access permissions.
AddressAlreadyInUse Only one use of an address is normally permitted.
AddressFamilyNotSupporte The address is incompatible with the requested protocol.
AddressNotAvailable The selected address is valid in this context.
AlreadyInProgress The nonblocking Socket already has an operation in progress.
ConnectionAborted The connection was aborted by the .NET Framework or the underlying
socket provider.
ConnectionRefused The remote host is actively refusing a connection.
ConnectionReset The connection was reset by the remote peer.
DestinationAddressRequired A required address was omitted from an operation on a Socket.
Disconnecting A graceful shutdown is in progress.
Fault An invalid pointer address was detected by the underlying socket provider.
HostDown The operation failed because the remote host is down.
HostNotFound No such host is known. The name is not an official host name or alias.
-
Socket Exception Enumerations
Member name Description
HostUnreachable There is no network route to the specified host.
InProgress A blocking operation is in progress.
Interrupted A blocking Socket call was cancelled.
InvalidArgument An invalid argument was supplied to a Socket member.
IOPending The application has initiated an overlapped operation that cannot be completed
immediately.
IsConnected The Socket is already connected.
MessageSize The datagram is too long.
NetworkDown The network is not available.
NetworkReset The application tried to set KeepAlive on a connection that has already timed out.
NetworkUnreachable No route to the remote host exists.
NoBufferSpaceAvailable No free buffer space is available for a Socket operation.
NoData The requested name or IP address was not found on the name server.
NoRecovery The error is unrecoverable or the requested database cannot be located.
-
Socket Exception Enumerations
Member name Description
NotConnected The application tried to send or receive data, and the Socket is not connected.
NotInitialized The underlying socket provider has not been initialized.
NotSocket A Socket operation was attempted on a non-socket.
OperationAborted The overlapped operation was aborted due to the closure of the Socket.
OperationNotSupported The address family is not supported by the protocol family.
ProcessLimit Too many processes are using the underlying socket provider.
ProtocolFamilyNotSupported The protocol family is not implemented or has not been configured.
ProtocolNotSupported The protocol is not implemented or has not been configured.
ProtocolOption An unknown, invalid, or unsupported option or level was used with a Socket.
ProtocolType The protocol type is incorrect for this Socket.
Shutdown A request to send or receive data was disallowed because the Socket has already
been closed.
SocketError An unspecified Socket error has occurred.
-
Socket Exception Enumerations
Member name Description
SocketNotSupported The support for the specified socket type does not exist in this address family.
Success The Socket operation succeeded.
SystemNotReady The network subsystem is unavailable.
TimedOut The connection attempt timed out, or the connected host has failed to respond.
TooManyOpenSockets There are too many open sockets in the underlying socket provider.
TryAgain The name of the host could not be resolved. Try again later.
TypeNotFound The specified class was not found.
VersionNotSupported The version of the underlying socket provider is out of range.
WouldBlock An operation on a non-blocking socket cannot be completed immediately.
-
Working with Sockets in .NET
Creating a TCP Stream Socket Application
Building a TCP Server
Building a TCP Client
Managing Exceptions with System.NET
Sockets
Setting and Retrieving Socket Options
-
Setting and Retrieving Socket
Options
SetSocketOption
Customise socket
SocketOptionLevel
SocketOptionName
Value to set for the socket option
GetSocketOption
-
SetSocketOption
Name Description
Socket.SetSocketOption
(SocketOptionLevel, SocketOptionName,
Boolean)
Sets the specified Socket option to the
specified Boolean value.
Socket.SetSocketOption
(SocketOptionLevel, SocketOptionName,
Byte[])
Sets the specified Socket option to the
specified value, represented as a byte
array.
Supported by the .NET Compact
Framework.
Socket.SetSocketOption
(SocketOptionLevel, SocketOptionName,
Int32)
Sets the specified Socket option to the
specified integer value.
Supported by the .NET Compact
Framework.
Socket.SetSocketOption
(SocketOptionLevel, SocketOptionName,
Object)
Sets the specified Socket option to the
specified value, represented as an object.
Supported by the .NET Compact
Framework.
-
Socket Option Levels
Enumeration
Used to specify at which level of the OSI model the option is applied
-
SocketOptionLevel
Member name Description
IP Socket options apply only to
IP sockets.
IPv6 Socket options apply only to
IPv6 sockets.
Socket Socket options apply to all
sockets.
Tcp Socket options apply only to
TCP sockets.
Udp Socket options apply only to
UDP sockets.
-
Socket Option Names
Defines the name of the parameter whose value is being set
Examples ReuseAddress
Linger
-
SocketOptionName
Member name Description
AcceptConnection The socket is listening.
AddMembership Add an IP group membership.
AddSourceMembership Join a source group.
BlockSource Block data from a source.
Broadcast Permit sending broadcast messages on the socket.
BsdUrgent Use urgent data as defined in RFC-1222. This option can be set only once; after it is set, it cannot be turned off.
ChecksumCoverage Set or get the UDP checksum coverage.
Debug Record debugging information.
DontFragment Do not fragment IP datagrams.
DontLinger Close the socket gracefully without lingering.
DontRoute Do not route; send the packet directly to the interface addresses.
DropMembership Drop an IP group membership.
DropSourceMembership Drop a source group.
Error Get the error status and clear.
-
SocketOptionName
Member name Description
ExclusiveAddressUse Enables a socket to be bound for exclusive access.
Expedited Use expedited data as defined in RFC-1222. This option can be set only once; after it is set, it cannot be turned off.
HeaderIncluded Indicates that the application provides the IP header for outgoing datagrams.
HopLimit Specifies the maximum number of router hops for an Internet Protocol version 6 (IPv6) packet. This is similar to Time to Live (TTL) for Internet Protocol version 4.
IPOptions Specifies the IP options to be inserted into outgoing datagrams.
IpTimeToLive Set the IP header Time-to-Live field.
KeepAlive Use keep-alives.
Linger Linger on close if unsent data is present.
MaxConnections Not supported; will throw a SocketException if used.
MulticastInterface Set the interface for outgoing multicast packets.
-
SocketOptionName
Member name Description
MulticastLoopback An IP multicast loopback.
MulticastTimeToLive An IP multicast Time to Live.
NoChecksum Send UDP datagrams with checksum set to zero.
NoDelay Disables the Nagle algorithm for send coalescing.
OutOfBandInline Receives out-of-band data in the normal data stream.
PacketInformation Return information about received packets.
ReceiveBuffer Specifies the total per-socket buffer space reserved for receives. This is unrelated to the maximum message size or the size of a TCP window.
ReceiveLowWater Specifies the low water mark for Receive operations.
ReceiveTimeout Receive a time-out. This option applies only to synchronous methods; it has no
effect on asynchronous methods such as the BeginSend method.
-
SocketOptionName
Member name Description
ReuseAddress Allows the socket to be bound to an address that is already in use.
SendBuffer Specifies the total per-socket buffer space reserved for sends. This is unrelated to the maximum message size or the size of a TCP window.
SendLowWater Specifies the low water mark for Send operations.
SendTimeout Send a time-out. This option applies only to synchronous methods; it has no effect on asynchronous methods such as the BeginSend method.
Type Get the socket type.
TypeOfService Change the IP header type of the service field.
UnblockSource Unblock a previously blocked source.
UpdateAcceptContext Updates an accepted socket's properties by using those of an existing socket. This is equivalent to using the Winsock2 SO_UPDATE_ACCEPT_CONTEXT socket option and is supported only on connection-oriented sockets.
UpdateConnectContext Updates a connected socket's properties by using those of an existing socket. This is equivalent to using the Winsock2 SO_UPDATE_CONNECT_CONTEXT socket option and is supported only on connection-oriented sockets.
UseLoopback Bypass hardware when possible.
-
ReuseAddress
By default only one socket may be bound to a local address that is already in use.
However, you may want to bind more than
one socket to a local address
The solution is the ReuseAddress
-
ReuseAddress
(throws
error)
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SocketReuseAddress
{
class Program
{
static void Main(string[] args)
{
try
{
//Establish the local endpoint for the socket
IPEndPoint ipEndPoint = new IPEndPoint(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], 11000);
//Create a TCP/IP Socket
Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind the socket to the local endpoint and listen to incoming sockets
sListener.Bind(ipEndPoint);
sListener.Listen(10);
//Create a new socket
Socket sListener2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind the socket to the local endpoint and listen to the incoming sockets
sListener2.Bind(ipEndPoint);
sListener2.Listen(10);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
//Stop console from closing
Console.ReadLine();
}
}
}
-
ReuseAddress
(fixed)
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SocketReuseAddress
{
class Program
{
static void Main(string[] args)
{
try
{
//Establish the local endpoint for the socket
IPEndPoint ipEndPoint = new IPEndPoint(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], 11000);
//Create a TCP/IP Socket
Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind the socket to the local endpoint and listen to incoming sockets
sListener.Bind(ipEndPoint);
sListener.Listen(10);
//Create a new socket
Socket sListener2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Adding ReuseAddress option to prevent error message
sListener2.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
//Bind the socket to the local endpoint and listen to the incoming sockets
sListener2.Bind(ipEndPoint);
sListener2.Listen(10);
Console.WriteLine("Sockets successfully bound.");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
//Stop console from closing
Console.ReadLine();
}
}
}
-
Linger
Linger (from dictionary.com) v. lingered, lingering, lingers
v. intr.
To be slow in leaving, especially out of reluctance; tarry. See Synonyms at stay1.
To remain feebly alive for some time before dying. To persist: an aftertaste that lingers. To proceed slowly; saunter. To be tardy in acting; procrastinate.
v. tr. To pass (a period of time) in a leisurely or aimless manner.
Linger has an enumeration, called LingerOption
-
Linger
// Send operations will time-out if //confirmation is not received within 1000 //milliseconds.
s.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000);
// The socket will linger for 10 seconds //after Socket.Close is called.
LingerOption lingerOption = new LingerOption (true, 10);
s.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
-
Basic Outline
An Overview of Sockets
Working with Sockets in .NET
Asynchronous Programming
Socket Permissions
-
Asynchronous Programming
Introduction
Creating an Asynchronous Client Application
Creating an Asynchronous Server Application
-
Asynchronous Programming
Most socket functions Indefinite time to complete
Blocked
Asynchronous programming Functions that cant afford to hang around
A connection does not block an application
Events can be.. Signalled
Non-signalled
-
Asynchronous Programming
Two event types
Automatic (set themselves back to non-signalled state when they are signalled)
Manual (stay signalled until manually reset to non-signalled state)
ManualResetEvent use to indicate that you
want your program to continue
The .NET Framework provides a delegate class for asynchronous operations.
The class is called AsyncCallback
-
Asynchronous Programming
Introduction
Creating an Asynchronous Client Application
Creating an Asynchronous Server Application
-
The flow of an asynchronous client
applicationOriginal Thread
Create Socket
Waiting
Waiting
Waiting and further processing
Close Socket
Initialise Connection Request: BeginConnect
ConnectCallBack()
Initialise Sending Request: BeginSend
SendCallBack()
Initialise Receiving Request: BeginReceive
Secondary Thread
ReceiveCallback()
-
Asynchronous Client
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace AsyncClientExample
{
///
/// Summary description for Class1.
///
public class AsyncClient
{
public static ManualResetEvent connectDone = new ManualResetEvent( false );
public static ManualResetEvent sendDone = new ManualResetEvent( false );
public static ManualResetEvent receiveDone = new ManualResetEvent( false );
public static string response = string.Empty;
public static string sb = string.Empty;
public static byte[] buffer = new byte[8192];
-
Asynchronous Client
//ConnectCallback is called when connection is ready
public static void ConnectCallback( IAsyncResult a )
{
Thread thr = Thread.CurrentThread;
Console.WriteLine( "ConnectCallback Thread State: " + thr.ThreadState );
Socket sktClient = (Socket) a.AsyncState;
sktClient.EndConnect( a );
Console.WriteLine("Socket connected to {0}", sktClient.RemoteEndPoint.ToString() );
//Signal connectDone event to inform other thread
//that connection is ready for use
connectDone.Set();
} //End public static void ConnectCallback( IAsyncResult a )
-
Asynchronous Client
//SendCallback is called when sending is complete
public static void SendCallback( IAsyncResult a )
{
Thread thr = Thread.CurrentThread;
Console.WriteLine( "SendCallback Thread State: " + thr.ThreadState );
Socket sktClient = (Socket) a.AsyncState;
int bytesSent = sktClient.EndSend( a );
Console.WriteLine( "Sent {0} bytes to server", bytesSent );
//Signal sentDone event
sendDone.Set();
} //End public static void SendCallback( IAsyncResult a )
-
Asynchronous Client
//ReceiveCallback is called when receiving is complete
public static void ReceiveCallback( IAsyncResult a )
{
Thread thr = Thread.CurrentThread;
Console.WriteLine( "ReceiveCallback Thread State: " + thr.ThreadState );
Socket sktClient = (Socket) a.AsyncState;
int bytesRead = sktClient.EndReceive( a );
if( bytesRead > 0 )
{
sb += Encoding.ASCII.GetString(buffer,0, bytesRead);
sktClient.BeginReceive( buffer, 0, buffer.Length, 0, new AsyncCallback( ReceiveCallback), sktClient );
}
else
{
//Signal receiveDone event
receiveDone.Set();
}
} //End public static void receiveCallback( IAsyncResult a )
-
Asynchronous Client
[STAThread]
static void Main(string[] args)
{
try
{
Thread thr = Thread.CurrentThread;
Console.WriteLine( "Main Thread State: " + thr.ThreadState );
IPHostEntry ipHost = Dns.Resolve( "127.0.0.1" );
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint( ipAddr, 11000 );
Socket sktClient = new Socket( AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp );
-
Asynchronous Client
//Create new thread to initiate the connection to //the server
sktClient.BeginConnect( endPoint, new AsyncCallback( ConnectCallback ), sktClient );
connectDone.WaitOne();
string data = "This is a test";
for( int i = 0; i < 72; i++ )
{
data += i.ToString() + ":" + (new string( '=', i ));
}
byte[] byteData = Encoding.ASCII.GetBytes( data + "." );
//Send data in a separate thread
sktClient.BeginSend( byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback( SendCallback ), sktClient );
-
Asynchronous Client
//Do something in the main thread
byte[] byteData = Encoding.ASCII.GetBytes( data + "." );
//Send data in a separate thread
sktClient.BeginSend( byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback( SendCallback ), sktClient );
//Do something in the main thread
for( int i = 0; i < 10; i++ )
{
Console.WriteLine( i );
Thread.Sleep( 10 );
}
//Wait until all sending is done
sendDone.WaitOne();
-
Asynchronous Client
//Start receiving data in a separate thread
sktClient.BeginReceive( buffer, 0, buffer.Length, SocketFlags.None,
new AsyncCallback( ReceiveCallback ), sktClient );
receiveDone.WaitOne();
Console.WriteLine( "Response received: {0} ", sb );
sktClient.Shutdown( SocketShutdown.Both );
sktClient.Close();
}
catch( Exception e )
{
Console.WriteLine( e.ToString() );
}
Console.ReadLine();
} //End Main
} //End Class
} //End Namespace
-
Asynchronous Programming
Introduction
Creating an Asynchronous Client Application
Creating an Asynchronous Server Application
-
Asynchronous Server
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace AsyncServerExample
{
///
/// Summary description for Class1.
///
class AsyncServer
{
//Buffer to send and receive data
public static byte[] buffer = new byte[8192];
//Event class to support synchronization
public static ManualResetEvent socketEvent = new ManualResetEvent( false );
-
[STAThread]
static void Main(string[] args)
{
Console.WriteLine( "Main Thread ID: " + AppDomain.GetCurrentThreadId() );
byte[] bytes = new byte[8192];
IPHostEntry ipHost = Dns.Resolve( Dns.GetHostName() );
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEnd = new IPEndPoint( ipAddr, 11000 );
Socket sListener = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
//Bind socket
sListener.Bind( localEnd);
//Start listening
sListener.Listen( 10 );
Console.WriteLine( "Waiting for a connection....." );
AsyncCallback aCallback = new AsyncCallback( AcceptCallback );
//Asynchronous method for accepting connections
sListener.BeginAccept( aCallback, sListener );
//Waiting for other threads to finish
socketEvent.WaitOne();
Console.Read();
} //End Main()
-
Method AcceptCallBack
public static void AcceptCallback( IAsyncResult ar )
{
Console.WriteLine( "AcceptCallback Thread ID: " +
AppDomain.GetCurrentThreadId() );
//Retrieved the socket
Socket listener = (Socket) ar.AsyncState;
//New socket
Socket handler = listener.EndAccept( ar );
handler.BeginReceive( buffer, 0, buffer.Length, 0,
new AsyncCallback( ReceivCallback), handler );
} //End public static void AcceptCallback( IAsyncResult ar )
-
public static void ReceiveCallback( IAsyncResult ar )
{
Console.WriteLine( "ReceiveCallback Thread ID: "+ AppDomain.GetCurrentThreadId() );
string content = string.Empty;
Socket handler = (Socket) ar.AsyncState;
int bytesRead = handler.EndReceive( ar );
//check for data
if( bytesRead > 0 )
{
//Append data to main string
content += Encoding.ASCII.GetString( buffer, 0, bytesRead );
//If end of message character is encountered
if( content.IndexOf( "." ) > -1 )
{
Console.WriteLine( "Read {0} bytes from socket. \n Data: {1}",content.Length, content );
byte[] byteData = Encoding.ASCII.GetBytes( content );
//Send data back to the client
handler.BeginSend( byteData, 0, byteData.Length, 0, new AsyncCallback( SendCallback ), handler );
}
else
{
//Otherwise receive remaining data
handler.BeginReceive( buffer, 0, buffer.Length, 0, new AsyncCallback( ReceiveCallback), handler );
}
}
} //End public static void ReceiveCallback( IAsyncResult ar )
-
public static void SendCallback( IAsyncResult ar )
{
Console.WriteLine( "SendCallback Thread ID: " +
AppDomain.GetCurrentThreadId() );
Socket handler = (Socket) ar.AsyncState;
//Send Data back to client
int bytesSent = handler.EndSend( ar );
Console.WriteLine( "Sent {0} bytes to Client. ", bytesSent );
handler.Shutdown( SocketShutdown.Send );
handler.Close();
//Set main thread event
socketEvent.Set();
} //End public static void SendCallback( IAsyncResult ar )
} //End class AsyncServer
} //End namespace AsyncServerExample
-
Basic Outline
An Overview of Sockets
Working with Sockets in .NET
Asynchronous Programming
Socket Permissions
-
Socket Permissions
Introduction
Using Imperative Security
Using Declarative Security
-
Socket Permissions
Help develop secure code Only the code that has permission to run in the current context can
be executed
Each code-access permission demonstrates one of the following rights: The right to access protected resources such as files The right to perform a protected operation such as accessing managed
code
SocketPermission class enforces code-access permissions Used to control rights to make or accept connections (control
connections via sockets)
Consists of host specification and a set of actions specifying ways to connect to the host
Enforces secure code by monitoring the values of the host name, IP address and transport protocol
-
Socket Permissions
There are two ways to enforce security permission in C# sockets: Imperatively
Implements permissions by creating a new instance of the SocketPermission class to demand a particular permission when the code is executed, such as the right to make a TCP connection. It is generally used when the security setting are changed at runtime.
Declaratively Declarative syntax uses attributes to place security
information into the metadata of your code, so that the client calls your code can use reflection to see what permissions are required by the code.
-
Imperative Security
Creates a new instance of the SocketPermissionclass to enforce security
Use imperative security syntax to perform demands and overrides, but not requests
Before calling the corresponding security measure, it is necessary to initialise the state of the SocketPermission class through the constructor so that it represents the particular form of permission that you want to use.
This kind of security is only useful when you have some information needed for security that is available only at runtime; for example; if you want to secure some host over a port but dont know the host name and port number until the program executes
-
Imperative
Security
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security;
using System.Security.Permissions;
namespace SocketsImperativeSecurity
{
class Program
{
static void Main(string[] args)
{
//Option could be either Assert or Deny passed on the command line
//If option is Assert, then the program executes successfully
//Otherwise, it triggers a SecurityException
string option = null;
if (args.Length > 0)
{
option = args[0];
}
else
{
option = "assert";
} //end of if-else
Console.WriteLine("option: " + option);
MethodA(option);
Console.WriteLine("Done");
}
-
public static void MethodA(string option)
{
Console.WriteLine("Method A");
IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
IPAddress ipAddress = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 11000);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketPermission permitSocket = new SocketPermission(NetworkAccess.Connect, TransportType.Tcp, "127.0.0.1", SocketPermission.AllPorts);
//Select assert or deny on the basis of paramter passed
if (option.Equals("deny"))
permitSocket.Deny();
else
permitSocket.Assert();
try
{
//Connect the socket to the romote endpoint. Catch an errors
sender.Connect(ipEndPoint);
Console.WriteLine("Socket connected to {0}.", sender.RemoteEndPoint.ToString());
byte[] bytes = new byte[1024];
byte[] msg = Encoding.ASCII.GetBytes("This is a test.");
//send the data through the socket
int bytesSent = sender.Send(msg);
//receive the response from the remote device
int bytesRec = sender.Receive(bytes);
-
Console.WriteLine("Echoed Test = {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
}
catch (SocketException s)
{
Console.WriteLine("Socket Exception: " + s.ToString());
}
catch (SecurityException se)
{
Console.WriteLine("Socket Exception: " + se.ToString());
} //end of catch
finally
{
if (sender.Connected)
{
//Release the socket
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
}
Console.WriteLine("Closing method A.");
Console.ReadLine();
} //end of MethodA
}
}
-
Declarative Security
Uses .NET attributes to place security information inside the metadata of the code
Attributes can be placed at the assembly, class or member level to indicate the type of request, demand, or override that is needed.
In order to use this security syntax, the state of the data must be initialised first for the SocketPermissionAttribute object through the declarative syntax, so that it represents the form of permission that is being enforced on the code.
-
Declarative Security
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security;
using System.Security.Permissions;
namespace SocketDeclarativeSecurity
{
class Program
{
static void Main(string[] args)
{
LegalMethod();
IllegalMethod();
Console.Write("Press a key to continue.");
Console.ReadLine();
}
-
Legal Method
[SocketPermission (SecurityAction.Assert, Access = "Connect", Host = "127.0.0.1", Port = "All", Transport = "Tcp")]
public static void LegalMethod()
{
Console.WriteLine("Legal Method");
IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
//Connect the socket to the remote endpoint. Catch any errors
sender.Connect(ipEndPoint);
Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString());
} //end of try
catch (SecurityException se)
{
Console.WriteLine("Security Exception: " + se);
} //end of catch
catch (SocketException se)
{
Console.WriteLine("Socket Exception: " + se);
} //end of catch
finally
{
if (sender.Connected)
{
//release the socket
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
} //end of finally
} // end of legalMethod
-
Illegal
Method
[SocketPermission(SecurityAction.Deny, Access = "Connect", Host = "127.0.0.1", Port = "All", Transport = "Tcp")]
public static void IllegalMethod()
{
Console.WriteLine("Illegal Method");
IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
//Connect the socket to the remote endpoint. Catch any errors
sender.Connect(ipEndPoint);
Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString());
} //end of try
catch (SecurityException se)
{
Console.WriteLine("Security Exception: " + se);
} //end of catch
catch (SocketException se)
{
Console.WriteLine("Socket Exception: " + se);
} //end of catch
finally
{
if (sender.Connected)
{
//release the socket
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
} //end of finally
}
}
}
-
Summary
Socket class Two main socket types
Stream sockets Datagram sockets
System.Net.Sockets namespace
SocketException Class Finally block should contain Close and Shutdown methods
Basic socket options Asynchronous programming model Security
Imperative Permissions known only at runtime
Declarative Permissions needed are known at compile-time