Mono Class Library: System.Net.Sockets Namespace

System.Net.Sockets.Socket Class

Creates a communication endpoint through which an application sends or receives data across a network.

See Also: Socket Members

public class Socket : IDisposable

Thread Safety

All public static members of this type are safe for multithreaded operations. No instance members are guaranteed to be thread safe.

Remarks

This class enables a System.Net.Sockets.Socket instance to communicate with another socket across a network. The communication can be through connection-oriented and connectionless protocols using either data streams or datagrams (discrete message packets).

Message-oriented protocols preserve message boundaries and require that for each Socket.Send(Byte[], int, SocketFlags) method call there is one corresponding Socket.Receive(Byte[], int, SocketFlags) method call. For stream-oriented protocols, data is transmitted without regards to message boundaries. In this case, for example, multiple Socket.Receive(Byte[], int, SocketFlags) method calls might be necessary to retrieve all the data from one Socket.Send(Byte[], int, SocketFlags) method call. The protocol is set in the Socket class constructor.

A System.Net.Sockets.Socket instance has a local and a remote endpoint associated with it. The local endpoint contains the connection information for the current socket instance. The remote endpoint contains the connection information for the socket that the current instance communicates with. The endpoints are required to be an instance of a type derived from the System.Net.EndPoint class. For the Transmission Control Protocol (TCP) and User Datagram Protocol (UDP) protocols, an endpoint includes the address family, an Internet Protocol (IP) address, and a port number. For connection-oriented protocols (for example, TCP), the remote endpoint does not have to be specified when transferring data. For connectionless protocols (for example, UDP), the remote endpoint is required to be specified.

Methods are provided for both synchronous and asynchronous operations. A synchronous method can operate in blocking mode, in which it waits (blocks) until the operation is complete before returning, or in non-blocking mode, where it returns immediately, possibly before the operation has completed. The blocking mode is set through the Socket.Blocking property.

An asynchronous method returns immediately and, by convention, relies on a delegate to complete the operation. Asynchronous methods have names which correspond to their synchronous counterparts prefixed with either 'Begin' or End'. For example, the synchronous Socket.Accept method has asynchronous counterpart methods named Socket.BeginAccept(AsyncCallback, object) and Socket.EndAccept(IAsyncResult). The example for the Socket.BeginAccept(AsyncCallback, object) method shows the basic steps for using an asynchronous operation. A complete working example follows this discussion.

Connection-oriented protocols commonly use the client/server model. In this model, one of the sockets is set up as a server, and one or more sockets are set up as clients. A general procedure demonstrating the synchronous communication process for this model is as follows.

On the server-side:

  1. Create a socket to listen for incoming connection requests.
  2. Set the local endpoint using the Socket.Bind(System.Net.EndPoint) method.
  3. Put the socket in the listening state using the Socket.Listen(int) method.
  4. At this point incoming connection requests from a client are placed in a queue.
  5. Use the Socket.Accept method to create a server socket for a connection request issued by a client-side socket. This sets the remote endpoint.
  6. Use the Socket.Send(Byte[], int, SocketFlags) and Socket.Receive(Byte[], int, SocketFlags) methods to communicate with the client socket.
  7. When communication is finished, terminate the connection using the Socket.Shutdown(SocketShutdown) method.
  8. Release the resources allocated by the server socket using the Socket.Close method.
  9. Release the resources allocated by the listener socket using the Socket.Close method.

On the client-side:

  1. Create the client socket.
  2. Connect to the server socket using the Socket.Connect(System.Net.EndPoint) method. This sets both the local and remote endpoints for the client socket.
  3. Use the Socket.Send(Byte[], int, SocketFlags) and Socket.Receive(Byte[], int, SocketFlags) methods to communicate with the server socket.
  4. When communication is finished, terminate the connection using the Socket.Shutdown(SocketShutdown) method.
  5. Release the resources allocated by the client socket using the Socket.Close method.

The shutdown step in the previous procedure is not necessary but ensures that any pending data is not lost. If the Socket.Shutdown(SocketShutdown) method is not called, the Socket.Close method shuts down the connection either gracefully or by force. A graceful closure attempts to transfer all pending data before the connection is terminated. Use the SocketOptionName.Linger socket option to specify a graceful closure for a socket.

Note:

This implementation is based on the UNIX sockets implementation in the Berkeley Software Distribution (BSD, release 4.3) from the University of California at Berkeley.

Example

The following examples provide a client/server application that demonstrates the use of asynchronous communication between sockets. Run the client and server on different consoles.

The following code is for the server application. Start this application before the client application.

C# Example

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

public class Server 
{
  // used to pass state information to delegate
  internal class StateObject 
  {
    internal byte[] sBuffer;
    internal Socket sSocket;
    internal StateObject(int size, Socket sock) {
      sBuffer = new byte[size];
      sSocket = sock;
    }
  }
  static void Main() 
  {
    IPAddress ipAddress =
      Dns.Resolve( Dns.GetHostName() ).AddressList[0];

    IPEndPoint ipEndpoint =
      new IPEndPoint(ipAddress, 1800);

    Socket listenSocket =
      new Socket(AddressFamily.InterNetwork,
                 SocketType.Stream,
                 ProtocolType.Tcp);

    listenSocket.Bind(ipEndpoint);
    listenSocket.Listen(1);
    IAsyncResult asyncAccept = listenSocket.BeginAccept(
      new AsyncCallback(Server.acceptCallback),
      listenSocket );

    // could call listenSocket.EndAccept(asyncAccept) here
    // instead of in the callback method, but since 
    // EndAccept blocks, the behavior would be similar to 
    // calling the synchronous Accept method

    Console.Write("Connection in progress.");
    if( writeDot(asyncAccept) == true ) 
    {
      // allow time for callbacks to
      // finish before the program ends 
      Thread.Sleep(3000);
    }
  }

  public static void
    acceptCallback(IAsyncResult asyncAccept) {
      Socket listenSocket = (Socket)asyncAccept.AsyncState;
      Socket serverSocket =
        listenSocket.EndAccept(asyncAccept);

      // arriving here means the operation completed
      // (asyncAccept.IsCompleted = true) but not
      // necessarily successfully
      if( serverSocket.Connected == false )
      {
        Console.WriteLine( ".server is not connected." );
        return;
      }
      else Console.WriteLine( ".server is connected." );

      listenSocket.Close();

      StateObject stateObject =
        new StateObject(16, serverSocket);

      // this call passes the StateObject because it 
      // needs to pass the buffer as well as the socket
      IAsyncResult asyncReceive =
        serverSocket.BeginReceive(
          stateObject.sBuffer,
          0,
          stateObject.sBuffer.Length,
          SocketFlags.None,
          new AsyncCallback(receiveCallback),
          stateObject);

      Console.Write("Receiving data.");
      writeDot(asyncReceive);
  }

  public static void
    receiveCallback(IAsyncResult asyncReceive) {
      StateObject stateObject =
        (StateObject)asyncReceive.AsyncState;
      int bytesReceived =
        stateObject.sSocket.EndReceive(asyncReceive);

      Console.WriteLine(
        ".{0} bytes received: {1}",
        bytesReceived.ToString(),
        Encoding.ASCII.GetString(stateObject.sBuffer) );

      byte[] sendBuffer =
        Encoding.ASCII.GetBytes("Goodbye");
      IAsyncResult asyncSend =
        stateObject.sSocket.BeginSend(
          sendBuffer,
          0,
          sendBuffer.Length,
          SocketFlags.None,
          new AsyncCallback(sendCallback),
          stateObject.sSocket);

      Console.Write("Sending response.");
      writeDot(asyncSend);
  }

  public static void sendCallback(IAsyncResult asyncSend) {
    Socket serverSocket = (Socket)asyncSend.AsyncState;
    int bytesSent = serverSocket.EndSend(asyncSend);
    Console.WriteLine(
      ".{0} bytes sent.{1}{1}Shutting down.",
      bytesSent.ToString(),
      Environment.NewLine );

    serverSocket.Shutdown(SocketShutdown.Both);
    serverSocket.Close();
  }

  // times out after 20 seconds but operation continues
  internal static bool writeDot(IAsyncResult ar)
  {
    int i = 0;
    while( ar.IsCompleted == false ) 
    {
      if( i++ > 40 ) 
      {
        Console.WriteLine("Timed out.");
        return false;
      }
      Console.Write(".");
      Thread.Sleep(500);
    }
    return true;
  }
}
   

The following code is for the client application. When starting the application, supply the hostname of the console running the server application as an input parameter (for example, ProgramName hostname ).

C# Example

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

public class Client {

  // used to pass state information to delegate
  class StateObject 
  {
    internal byte[] sBuffer;
    internal Socket sSocket;
    internal StateObject(int size, Socket sock) {
      sBuffer = new byte[size];
      sSocket = sock;
    }
  }

  static void Main(string[] argHostName) 
  {
    IPAddress ipAddress =
      Dns.Resolve( argHostName[0] ).AddressList[0];

    IPEndPoint ipEndpoint =
      new IPEndPoint(ipAddress, 1800);

    Socket clientSocket = new Socket(
      AddressFamily.InterNetwork,
      SocketType.Stream,
      ProtocolType.Tcp);

    IAsyncResult asyncConnect = clientSocket.BeginConnect(
      ipEndpoint,
      new AsyncCallback(connectCallback),
      clientSocket );

    Console.Write("Connection in progress.");
    if( writeDot(asyncConnect) == true ) 
    {
      // allow time for callbacks to
      // finish before the program ends
      Thread.Sleep(3000);
    }
  }

  public static void
    connectCallback(IAsyncResult asyncConnect) {
      Socket clientSocket =
        (Socket)asyncConnect.AsyncState;
      clientSocket.EndConnect(asyncConnect);
      // arriving here means the operation completed
      // (asyncConnect.IsCompleted = true) but not
      // necessarily successfully
      if( clientSocket.Connected == false )
      {
        Console.WriteLine( ".client is not connected." );
        return;
      }
      else Console.WriteLine( ".client is connected." );

      byte[] sendBuffer = Encoding.ASCII.GetBytes("Hello");
      IAsyncResult asyncSend = clientSocket.BeginSend(
        sendBuffer,
        0,
        sendBuffer.Length,
        SocketFlags.None,
        new AsyncCallback(sendCallback),
        clientSocket);

      Console.Write("Sending data.");
      writeDot(asyncSend);
  }

  public static void sendCallback(IAsyncResult asyncSend) 
  {
    Socket clientSocket = (Socket)asyncSend.AsyncState;
    int bytesSent = clientSocket.EndSend(asyncSend);
    Console.WriteLine(
      ".{0} bytes sent.",
      bytesSent.ToString() );

    StateObject stateObject =
      new StateObject(16, clientSocket);

    // this call passes the StateObject because it
    // needs to pass the buffer as well as the socket
    IAsyncResult asyncReceive =
      clientSocket.BeginReceive(
        stateObject.sBuffer,
        0,
        stateObject.sBuffer.Length,
        SocketFlags.None,
        new AsyncCallback(receiveCallback),
        stateObject);

    Console.Write("Receiving response.");
    writeDot(asyncReceive);
  }

  public static void
    receiveCallback(IAsyncResult asyncReceive) {
      StateObject stateObject =
       (StateObject)asyncReceive.AsyncState;

      int bytesReceived =
        stateObject.sSocket.EndReceive(asyncReceive);

      Console.WriteLine(
        ".{0} bytes received: {1}{2}{2}Shutting down.",
        bytesReceived.ToString(),
        Encoding.ASCII.GetString(stateObject.sBuffer),
        Environment.NewLine );

      stateObject.sSocket.Shutdown(SocketShutdown.Both);
      stateObject.sSocket.Close();
  }

  // times out after 2 seconds but operation continues
  internal static bool writeDot(IAsyncResult ar)
  {
    int i = 0;
    while( ar.IsCompleted == false ) 
    {
      if( i++ > 20 ) 
      {
        Console.WriteLine("Timed out.");
        return false;
      }
      Console.Write(".");
      Thread.Sleep(100);
    }
    return true;
  }
}
   

The output of the server application is

Connection in progress...........server is connected.
Receiving data......5 bytes received: Hello
Sending response....7 bytes sent.
Shutting down.
-----------------------------------------

The output of the client application is

Connection in progress......client is connected.
Sending data......5 bytes sent.
Receiving response......7 bytes received: Goodbye
Shutting down.

Requirements

Namespace: System.Net.Sockets
Assembly: System (in System.dll)
Assembly Versions: 1.0.x.x, 1.0.5000.0, 2.0.0.0