Programming with Native Sockets

The native sockets interface is a managed code wrapper around the WinSock32 API, exposing the underlying socket system of the Windows operating system. For the most part, the .NET socket classes simply provide a one-to-one wrapper around the unmanaged code.

Java programmers are used to working with sockets at a higher level. The .NET socket classes allow for absolute control over Windows-based network programming but achieve this with increased complexity and demand a deeper understanding of network programming from the developer.

Creating Sockets

Sockets are created by specifying an address family, a socket type, and a protocol type. The address family is the address format that will be used to construct packets. The System.Net.Sockets.AddressFamily contains a large range of families, but the most commonly used is InterNetwork, representing IP version 4 (IPv4). The socket type represents the communication mode of the socket, represented by a value from the System.Net.Sockets.SocketType enumeration. The final element is the protocol type, represented by a value from the System.Net.Sockets.ProtocolType enumeration. Here is an example of creating a TCP and a UDP socket:

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

Socket x_udp_socket = new Socket(
    AddressFamily.InterNetwork,
    SocketType.Dgram,
    ProtocolType.Udp);

Client Sockets

The following example demonstrates how to use the socket classes to request the index page from the Microsoft HTTP server:

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

IPHostEntry x_hostentry = Dns.GetHostByName("www.microsoft.com");
IPEndPoint x_endpoint =
    new IPEndPoint(x_hostentry.AddressList[0], 80);
x_socket.Connect(x_endpoint);

x_socket.Send(Encoding.ASCII.GetBytes("GET / HTTP/1.0

"));

byte[] x_byte = new byte[100];
int x_read;
while ((x_read = x_socket.Receive(x_byte)) > 0) {
    Console.Write(Encoding.ASCII.GetString(x_byte, 0, x_read));
}

x_socket.Shutdown(SocketShutdown.Both);
x_socket.Close();

The obvious changes between using the Socket class instead of TcpListener have largely to do with convenience:

  • Connections must be made using an EndPoint.

  • Sending and receiving data is done using byte arrays. There is no stream support in the Socket class.

  • Data cannot be buffered.

  • There are no convenience methods for configuring the socket connection.

Once connected, data can be sent to the server using the Send or SendTo method. The SendTo method is useful only for connectionless protocols, such as UDP, in which the target for the message needs to be specified. To receive data from the server, a byte array must be passed into the Receive or ReceiveFrom method, which returns the number of bytes read.

When a socket is no longer required, the Shutdown method must be called, followed by Close. Shutdown specifies whether the socket I/O should be closed for reading, writing, or both, based on values contained in the Socket-Shutdown enumeration.

Server Sockets

The following example demonstrates a native socket implementation of the simple time server from earlier in this chapter. A client connects, and the server writes out the current time:

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

IPHostEntry x_hostentry = Dns.Resolve(Dns.GetHostName());
IPEndPoint x_endpoint = new IPEndPoint(x_hostentry.AddressList[0],
    20172);

x_server_socket.Bind(x_endpoint);
x_server_socket.Listen(5);

while (true) {
    Socket x_socket = x_server_socket.Accept();

    byte[] x_msg = Encoding.ASCII.GetBytes("The time is "
        + DateTime.Now.ToShortTimeString());

    x_socket.Send(x_msg);
    x_socket.Shutdown(SocketShutdown.Both);
    x_socket.Close();

}

This example demonstrates that the connections are handled in much the same way as with java.net.ServerSocket. The Bind method indicates that this socket will be used to receive client connections, and the Listen method signals that the socket should be placed in a listening mode. Connections are accepted with the Accept method and return a Socket representing the connection to the client.

Configuring Sockets

The Socket class exposes options that can be set for a connection. A treatise on socket programming is outside the scope of this book, but we will explain how options are set, using some commonly understood examples. Setting socket options requires three elements:

  • The level at which the option applies, defined by the SocketOptionLevel enumeration:

    • IP, affecting all IP sockets

    • Socket, affecting individual socket instances

    • Tcp, affecting TCP sockets

    • Udp, affecting UDP sockets

  • The name of the socket option, from the set in the SocketOptionName enumeration. Consult the .NET documentation for a complete listing.

  • The value of the options, which can be expressed as a byte array, an int, or an object. We recommend consulting the WinSock32 reference guide for more details.

The following example demonstrates how to set an option:

x_socket.SetSocketOption(SocketOptionLevel.Tcp,
    SocketOptionName.SendTimeout, 2000);

This option sets the amount of time the socket will wait for the other party to acknowledge data sent with the Send method.

Asynchronous Sockets

The main advantage of using the Socket class is that almost all operations can be performed asynchronously, which is useful for large-scale applications. The details of asynchronous I/O are covered in Chapter 10, but the Socket class also allows connections to be made and received in this manner.

Table 14-15 details the methods that are available for asynchronous programming in the Socket class.

Table 14-15. The Asynchronous Methods in the Socket Class

Method

Synchronous Method

Description

BeginAccept()

Accept()

Accepts a connection from a client

EndAccept()

  

BeginConnect()

Connect()

Creates a connection to a server

EndConnect()

  

BeginReceive()

Receive()

Reads data from a socket into a byte array

BeginReceiveFrom()

ReceiveFrom()

 

EndReceive()

  

EndReceiveFrom()

  

BeginSend()

Send()

Sends data to a connected socket

BeginSendTo()

SendTo()

 

EndSend()

  

EndSendTo()

  
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset