Sunteți pe pagina 1din 81

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
Port

Server

Connection Request

Client

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.
If everything goes well, provided that the server is running
Port
before the client tries to connect to it, the server accepts
Server
the connection. Upon acceptance, the server application
create a new socket to deal specifically with the connect
Port
client.
The client and the server can now communicate with each
other by reading from and writing to their respective
Port
Client sockets.
Start
communication

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
Properties
AddressFamily

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
Properties
ProtocolType

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 TCbased
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
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Net.Sockets;
Note: System.Net & System.Net.Sockets
System.Net;

namespace TestSockets
{
class SocketServer
Returns all network
{
addresses supported
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

//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
The Bind method associates a socket with a local
try
endpoint. You must call Bind before any attempt to call
{
Listen or Accept.
sListener.Bind(ipEndPoint);
sListener.Listen(10);
The maximum pending connections
while (true)
{
Console.WriteLine("Waiting for connection on port
{0}.", ipEndPoint);

//program is suspended while waiting for an incoming


connection
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.

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("<TheEnd>") > -1)
break;
}//end of while

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

Client

Building
a TCbased
Client

Open a Socket
(Socket)

Connect to Remote Host


(Connect)

Send/Receive Data
(Send/Receive)

Close Socket
(Close)

using
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Net.Sockets;
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 + "<TheEnd>");
//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 <= 1024; i++)
{
Console.WriteLine("Checking port {0}", i.ToString());
try
{
//Establish the remote endpoint for the socket
IPEndPoint endPoint = new IPEndPoint(address, i);
sSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);

//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 <= count; ++j)
Console.WriteLine("Port {0} is listening.",
listeningPorts[j].ToString());
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

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 Enumerations


Member 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.
Socket options apply only to
IPv6 sockets.

IPv6
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

using
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Net;
System.Net.Sockets;

ReuseAddress
(throws
error)

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();
}
}
}

using
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Net;
System.Net.Sockets;

ReuseAddress
(fixed)

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 nonsignalled 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


application
Original Thread

Secondary Thread

Create Socket
Initialise Connection Request: BeginConnect
Waiting

ConnectCallBack()
Initialise Sending Request: BeginSend

Waiting

SendCallBack()
Initialise Receiving Request: BeginReceive

Waiting and further processing


ReceiveCallback()
Close Socket

Asynchronous Client
using
using
using
using
using

System;
System.Net;
System.Net.Sockets;
System.Text;
System.Threading;

namespace AsyncClientExample
{
/// <summary>
/// Summary description for Class1.
/// </summary>
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>
/// Summary description for Class1.
/// </summary>
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 );
bytesSent );

Console.WriteLine( "Sent {0} bytes to Client. ",


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 SocketPermission
class 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

using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Net;
System.Net.Sockets;
System.Security;
System.Security.Permissions;

Imperative
Security

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.<EOF>");
//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
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Net;
System.Net.Sockets;
System.Security;
System.Security.Permissions;

namespace SocketDeclarativeSecurity
{
class Program
{
static void Main(string[] args)
{
LegalMethod();
IllegalMethod();
Console.Write("Press a key to continue.");
Console.ReadLine();
}

[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

Legal 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
}

Illegal
Method

}
}

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

S-ar putea să vă placă și