Socket Basics


Now that you have a basic understanding of the common IP-based networking protocols, it s time to get into the specifics of creating sockets as well as what steps are involved in using sockets to send and receive data. Your first question is probably What exactly is a socket? A socket is an object that describes a network resource that s the underlying network protocol that the application is using for communication. The following sections will describe how an application creates a socket and puts it into a state so that it can be used to send and receive data. The Socket class resides in the System.Net namespace.

Socket basics are illustrated in the SimpleSocket sample located under the Chap08\SimpleSocket directory. The sample illustrates using the Socket class for simple TCP and UDP cases.

Creating

The first step in the process is creating the socket by instantiating an instance of the Socket class, which is shown here:

C#

 publicsocket(AddressFamilyaddressFamily, SocketTypesocketType, ProtocolTypeprotocolType); 

Visual Basic .NET

 PublicSubNew(_ ByValaddressFamilyAsAddressFamily,_ ByValsocketTypeAsSocketType,_ ByValprotocolTypeAsProtocolType_) 

The three parameters to the constructor define exactly which network protocol is to be created. The first parameter is an enumerated type that defines the addressing protocol to be used. The two values of this enumeration that are of interest to us are InterNetwork for the IPv4 protocol and InterNetworkV6 for the IPv6 protocol.

The second and third parameters are closely related to one another and determine which upper-level protocol the socket being created is. The SocketType enumeration indicates the protocol s semantics in terms of how data is sent and received. For example, the SocketType.Dgram value indicates that the protocol is message- (or datagram-) oriented such that message boundaries are preserved on receive. For example, if a datagram socket sends 100 bytes, a single-100 byte packet is put on the network wire and the receiving datagram socket will receive exactly 100 bytes in a single receive call. Table 8-1 lists the values of the SocketType enumeration and describes their meanings.

Table 8-1: Common SocketType Values

SocketType Member

Description

Dgram

Datagram-oriented, where each send on a datagram socket represents a packet on the network such that message boundaries are preserved at the receiver

Raw

Raw protocol socket where the sender intends to build its own next protocol header as a part of the data payload

Rdm

Reliable datagram socket where the socket is datagram- oriented but is also reliable

Seqpacket

Sequential packet or pseudostream socket where each send on the socket represents a packet on the network but message boundaries are not preserved on the receiver side

Stream

Stream-oriented socket where both the sender and receiver can lump data in any size during sending or receiving of data

Unknown

Unspecified socket type where the network stack will attempt to find a protocol that matches the given AddressFamily and ProtocolType parameters

The last parameter indicates the exact protocol to be used for the indicated AddressFamily and SocketType . The protocols we re interested in are ProtocolType.Tcp and ProtocolType.Udp . Note that for the TCP protocol, SocketType.Stream must be specified for the socket type, and for the UDP protocol, SocketType.Dgram is required. The TCP and UDP protocol have exact semantics; however, there are a few protocols, such as SPX, that allow for differing behavior ( Stream and Seqpacket ). If an invalid combination of socket type and protocol type are given, the SocketException error is thrown.

Binding

Once you have created a socket, it can t be used for data transfer until it s bound to a network interface. All data sent must originate from an address that s associated with a physical network interface, and likewise, all data received must be read from a physical interface. The process of binding a socket to a local interface is simple. First an address object must be created that describes the local address that the socket is to be bound to. In the case of IPv4 and IPv6, this address object is the IPAddress class. Either an IPAddress object is initialized with a property of the IPAddress class itself, or the Parse method is used to parse the string representation of an address into the object. Table 8-2 lists the commonly used properties and methods for binding to an interface.

Table 8-2: IPAddress Members

Member

Property/Method

Description

Any

Property

IPv4 wildcard address: 0.0.0.0

Broadcast

Property

IPv4 broadcast address: 255.255.255.255

Loopback

Property

IPv4 loopback address: 127.0.0.1

Ipv6Any

Property

IPv6 wildcard address: ::

Ipv6Loopback

Property

IPv6 loopback address: ::1

Parse

Method

Parses a string into the appropriate protocol

The following code illustrates how to initialize several different IPAddress objects with properties by using the Parse method:

C#

 IPAddressbindAddress,parsedAddress; bindAddress=IPAddress.Any;//HoldstheIPv4wildcardaddress bindAddress=IPAddress.IPv6Any;//NowholdstheIPv6wildcardaddress try { parsedAddress=IPAddress.Parse("169.254.0.1"); parsedAddress=IPAddress.Parse("fe80::2ff:abcd:1234%3"); } catch(FormatExceptionerr) { Console.WriteLine("InvalidIPaddress:{0}",err.Message); } 

Visual Basic .NET

 DimbindAddressAsIPAddress,parsedAddressAsIPAddress bindAddress=IPAddress.AnyHoldstheIP4wildcardaddress bindAddress=IPAddress.IPv6AnyNowholdstheIPv6wildcardaddress Try parsedAddress=IPAddress.Parse(169.254.0.1) ParsedAddress=IPAddress.Parse(fe80::2ff:abcd:1234%3) CatcherrAsFormatException Console.WriteLine(InvalidIPAddress:{0}",err.Message) EndTry 

Notice that the IPAddress class can contain either an IPv4 or IPv6 address. If an invalid IP address is passed to the Parse method, a FormatException is thrown.

Note  

Support for the IPv6 protocol in the IPAddress class was introduced in version 1.1 of the .NET Framework. Earlier versions of the IPAddress class can t be used to parse and describe IPv6 addresses.

Next create an EndPoint object corresponding the address object. An endpoint is a combination of the local address and a local port number. A port number is a 16-bit integer used by both the TCP and UDP protocols for multiplexing multiple sockets on a single interface. This way, if a UDP packet arrives on interface 10.10.10.1 and port 5150, the stack will deliver the data to the socket bound to the same interface and port. To create an endpoint for either the IPv4 or IPv6 protocol, an IPEndPoint object needs to be created. The following code creates an end point describing the IPv4 wildcard address on port 5150:

C#

 IPAddressbindAddress=IPAddress.Any; IPEndPointbindEndPoint=newIPEndPoint(bindAddress,5150); 

Visual Basic .NET

 DimbindAddressAsIPAddress=IPAddress.Any DimbindEndPointAsIPEndPoint=NewIPEndPoint(bindAddress,5150) 

Once the socket is created and an IPEndPoint is built, the Bind method needs to be called with IPEndPoint , as shown in the following code. Notice that the IPAddress is created from a user -input string that can be either an IPv4 or IPv6 string because the Parse method will parse either. Therefore, we make sure to parse the string first and then create the Socket with the proper address family by passing the AddressFamily property of the IPAddress to the socket creation call. If the address families of IPEndPoint and the created socket do not match, a SocketException occurs.

C#

 IPAddressbindAddress=IPAddress.Parse(userInputString); IPEndPointbindEndPoint=newIPEndPoint(bindAddress,5150); SocketmySocket=null; try { mySocket=newSocket(bindAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); mySocket.Bind(bindEndPoint); } catch(SocketExceptionerr) { if(mySocket!=null) mySocket.Close(); } 

Visual Basic .NET

 DimbindAddressAsIPAddress=IPAddress.Parse(userInputString) DimbindEndPointAsIPEndPoint=NewIPEndPoint(bindAddress,5150) DimmySocketAsSocket mySocket=Nothing Try mySocket=NewSocket(_ bindAddress.AddressFamily,_ SocketType.Stream,_ ProtocolType.Tcp) mySocket.Bind(bindEndPoint) CatcherrAsSocketException If(NotmySocketIsNothing)Then mySocket.Close() EndIf EndTry 

Note that binding a socket is not always required. The following operations will implicitly bind a socket to a local interface:

  • Connect

  • SendTo (for a datagram socket)

When one of these methods is called on an unbound socket, the network stack will bind the socket to an appropriate interface on a randomly chosen port in the range of 1024 to 5000. The advantage to explicitly binding the socket yourself is the ability to choose a specific port from the entire range of available ports, which will be discussed in more detail in the next chapter.

The most common cause of exceptions when calling the Bind method is when a socket of the same protocol is already bound to the requested port. For example, if UDP socket A is bound to address and port 10.10.10.1:5150, UDP socket B will get an exception if it attempts to bind to the same address and port. Note that if socket B is a TCP socket, no error will occur because the port reservations are on a per-protocol basis. In the Socket Options section later in this chapter, we ll cover several options that can allow several sockets of the same protocol to be bound to the same address and port. We ll also discuss this problem in detail in Chapter 9 because servers typically run into this problem more often than client sockets.

Connecting

Once a socket is created and optionally bound, it can be used as a client socket connected to a remote server. When a TCP socket is connected, the underlying protocol establishes a virtual circuit where the server actively accepts the connection if it chooses. If a connect is performed on a UDP socket, a destination address is associated with the socket so that if data is sent, the destination does not have to be supplied on each and every send call. Note that connecting a UDP socket by no means implies that a socket is waiting to receive the data on the destination ”it s simply a time-saving measure.

Connecting a socket is similar to binding except that instead of a local address in the end point, a remote address is specified. The port number used to create the IPEndPoint must be a valid port number on which the remote server is listening. In the case of TCP, if there s no active listening socket on the given port, a SocketException occurs because the remote computer will forcefully reject the connection. Again, for UDP, there will be no indication as to whether a socket is listening on the destination computer.

Most client applications typically resolve the server s host name using the Dns class to retrieve the list of addresses registered to the server computer. For more information about the Dns class, see Chapter 7. A robust client application should perform the following steps:

  1. Call Dns.Resolve with the server s host name.

  2. Iterate through the IPHostEntry.AddressList .

  3. Create a Socket based on the address family of the current IPAddress returned.

  4. Call Connect on the created socket to the current IPAddress .

  5. If the connection request fails, go to step 2.

  6. If the connection request succeeds, break out of the loop.

Performing these steps will ensure a positive user experience because an application should attempt to connect to the requested server on every address returned, not just the first address returned from DNS. The following code illustrates a simple TCP client that follows the above steps:

C#

 SockettcpSocket=null; IPHostEntryresolvedServer; IPEndPointserverEndPoint; try { resolvedServer=Dns.Resolve("server-name"); foreach(IPAddressaddrinresolvedServer.AddressList) { serverEndPoint=newIPEndPoint(addr,5150); tcpSocket=newSocket(addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { tcpSocket.Connect(serverEndPoint); } catch { //Connectfailedsotrythenextone //Makesuretoclosethesocketweopened if(tcpSocket!=null) tcpSocket.Close(); continue; } break; } } catch(SocketExceptionerr) { Console.WriteLine("Clientconnectionfailed:{0}",err.Message); } //NowusetcpSockettocommunicatetotheserver 

Visual Basic .NET

 DimtcpSocketAsSocket DimresolvedServerAsIPHostEntry DimserverEndPointAsIPEndPoint DimaddrAsIPAddress tcpSocket=Nothing Try resolvedServer=Dns.Resolve(server-name) ForEachaddrInresolvedServer.AddressList serverEndPoint=NewIPEndPoint(addr,5150) tcpSocket=NewSocket(_ addr.AddressFamily,_ SocketType.Stream,_ ProtocolType.Tcp_) Try tcpSocket.Connect(serverEndPoint) Catch Connectfailedsotrythenextone Makesuretoclosethesocketweopened If(NottcpSocketIsNothing)Then tcpSocket.Close() EndIf GoToContinueLoop EndTry ContinueLoop: Next CatcherrAsSocketException Console.WriteLine(Clientconnectionfailed:{0}",err.Message) EndTry 


Network Programming for the Microsoft. NET Framework
Network Programming for the MicrosoftВ® .NET Framework (Pro-Developer)
ISBN: 073561959X
EAN: 2147483647
Year: 2003
Pages: 121

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net