Underlying Protocols


A thorough understanding of the underlying transport protocol is necessary for writing a good network application. Many protocols were designed for the lowest common denominatorhigh-latency, low-bandwidth connectionsperfect for connections over a 2400 baud modem or a satellite link. Unfortunately, this tends to cause problems on the fast Local Area Networks (LANs) of today, which is why its important to have an understanding of the protocols design. The most prevalent protocols in use are Transmission Control Protocol (TCP) and User Datagram Protocol (UDP).

Transmission Control Protocol (TCP)

TCP is the underlying transport for HTTP and is commonly used by socket- based applications. TCP offers several advantages such as being connection- based, reliable, and able to support flow control; however, it also has several possible disadvantages.

One of the most common mistakes using TCP occurs when applications serialize calls between sending and receiving. That is, an application will send data, wait for the send to complete, and then receive data. After data is received, another send is made. This practice is undesirable because TCP is a bidirectional protocol where the sending and receiving paths are independent of one another. Alternating between calls to send and calls to receive means an application cannot use bandwidth available for sending, as it is frequently blocked by a receive operation.

A good application should be receiving data at all times. This is because each side of a TCP connection advertises what is called a TCP window to the peer. The window is the number of bytes that the peer can send in such a way that the local sides receive buffers wont be overrun . If a peer is sending so much data that the receiving side cant keep up, the window size will go to 0, which tells the peer to stop sending data. If this occurs, your application will alternate between bursts of data and periods of no data being transmitted, which is an inefficient use of the network. An application should have separate send-and-receive operations so that it can receive data as fast as it can.

Another common problem with TCP is having many connections in the TIME_WAIT state. The TCP protocol defines several states for a connection, and when a connection is closed the peer receives indication of the closure. At this point, the side initiating the close waits for an acknowledgement of its close request by the peer. It then waits for the peer to send its own request to close the connection (since TCP is bidirectional, each side must close the connection), which must be acknowledged when it arrives. Whichever side initiates the close request goes into the TIME_WAIT state. The connection can remain in this state for minutes while it ensures that all outstanding data is properly acknowledged.

The TIME_WAIT state is important because the combination of a local IP address and port along with a remote IP address and port must be unique to successfully establish a connection. For example, if a client from 10.10.10.1:5000 makes a connection to a server address of 10.10.10.2:5150, then another connection from 10.10.10.1:5000 cannot be established because the identifier for the TCP connection would no longer be unique. This isnt a problem when the client connection is active; however, if the server actively initiates the close, the connection described by 10.10.10.1:5000,10.10.10.2:5150 goes into the TIME_WAIT state. The client receives notification that the connection was closed and can close its socket, but if the client attempts another connection to the server from the same address and port of the previous connection that is in TIME_WAIT on the server, it will be refused .

The solution to this problem is to have the client actively initiate the close so that the connection on the client side goes into TIME_WAIT state. This is less problematic since most client sockets do not bind to an explicit local port. By contrast, servers must bind to a well known port for clients to know how to reach them. In the example, the connection would succeed if the client actively initiated the close and then connected to the server from a different local port.

Implicit socket binding is another important issue many developers encounter with TCP. A server socket is always bound to a well-known port so that clients know how to reach it, but most clients either do not explicitly bind the socket before calling connect or they bind to the wildcard address and port zero. A client that does not call bind explicitly will have the socket bound implicitly to a local port in the range of 1024 to 5000 when a connection request is made.

A final issue that can be disadvantageous in TCP (and HTTP) applications is the Nagle algorithm. When data is sent on a connection, the Nagle algorithm causes network stack delays for a brief moment (up to 200 milliseconds ) to see if the application will make another send call. It does this so that the data may be consolidated into a single TCP packet. If the stack were to send the data in its own TCP packet for every send by the application, the majority of the packets would contain a relatively small amount of data. This makes for a congested network as each TCP packet send adds 20 bytes for the IP header and 20 bytes for the TCP header.

Most applications never need to disable the Nagle algorithm, and doing so can degrade network performance, but there are certain classes of applications that do require data to be sent immediately. Applications that return user feedback sometimes need to disable Nagling to be responsive extra delays in sending data that result in feedback to the user might be perceived as a hang. Applications that send small amounts of data infrequently also benefit from disabling Nagling as the network delay is unnecessary in these cases.

Using the Socket class, the Nagle algorithm is disabled by calling the SetSocketOption method with SocketOptionLevel.Tcp and SocketOptionName.NoDelay . For Web requests such as using the WebRequest or HttpWebRequest class, the ServicePoint object associated with a request exposes a Boolean property, UseNagleAlgorithm , which can be set to false.

User Datagram Protocol (UDP)

Unlike TCP, the UDP protocol is very basic with few or no restrictions on how to use it. UDP is connectionless, so there is no overhead associated with establishing a connection before data can be transmitted. UDP also makes no guarantee that data will be delivered, which greatly simplifies its designjust send and forget.

However, these freedoms can lead to problems. Because UDP is connectionless, a single UDP socket can be used to send datagrams to several endpoints, but each socket object within the networking stack possesses a lock that must be acquired to send data. No other send operations can be performed on the socket while the lock is held. Therefore, if data is being sent on a single socket to multiple destinations, the sends are serialized, which can degrade performance. A better solution is to use multiple UDP sockets to send datagrams to different endpoints.

UDP is also unreliable. If an application sends too many datagrams simultaneously , some datagrams can be dropped in the network stack before they are sent. The stack maintains a limited number of buffers to use for sending datagrams. Therefore, data can be dropped when the network stack runs out of buffer space. No error message is indicated to the sender when data loss occurs. This scenario typically happens when a Socket posts too many asynchronous BeginSendTo operations. If you use blocking SendTo , youll rarely encounter this problem.

The Address Resolution Protocol (ARP) plays a part in UDP unreliability. When a UDP datagram is sent to a new destination that has not been sent to before, the network stack must determine whether the destination resides on the local network. The network stack must also determine whether the UDP packet must be sent to the default gateway, so that the packet is routed to its destination. The ARP protocol resolves the IP destination address into a physical Ethernet address. When the network stack determines that there is no ARP entry for a given IP destination, it makes an ARP request. As a result, the first UDP datagram is silently discarded while the ARP request is made. Developers should be aware of this behavior if their applications assume that the local network is quiet and the destination will receive all sent packetsapplications should send the first packet twice or implement reliability on top of UDP.




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