Computer Networks with (Network Programming) Introduction to Programming with UDP Lecture #8 Department of Electrical and Electronics Engineering Çukurova University TCP vs UDP Both use port numbers Application-specific construct serving as a communication endpoint 16-bit unsigned integer, thus ranging from 0 to 65535 ) To provide end-to-end transport UDP: User Datagram Protocol No acknowledgements No retransmissions Out of order, duplicates possible connectionless, i.e., app indicates destination for each packet TCP: Transmission Control Protocol Reliable byte-stream channel (in order, all arrive, no duplicates) similar to file I/O flow control, connection-oriented, bidirectional Connectionless In network, connectionless describes communication between two network end points in which a message can be sent from one end point to another without prior arrangement. Connectionless sockets allow the sending of messages in self-contained packets. A single read method reads the entire message sent by a single sent method. The User Datagram Protocol (UDP) is one of the core members of the Internet Protocol Suite, the set of network protocols used for the Internet. Connectionless-II A connectionless network provides minimal services. Connection-oriented methods may be implemented in the data link layers of the protocol stack and/or in the transport layers of the protocol stack, and the services required by the systems. UDP UDP uses a simple transmission model without implicit hand-shaking dialogues for guaranteeing reliability, ordering, or data integrity. Thus, UDP provides an unreliable service and datagrams may arrive out of order, appear duplicated, or go missing without notice. UDP assumes that error checking and correction is either not necessary or performed in the application, avoiding the overhead of such processing at the network interface level. 1
Why is there an UDP? Time-sensitive applications often use UDP because dropping packets is preferable to using delayed packets. Unfortunately, UDP packets are not guaranteed to arrive at their destination. Many factors, such as busy networks, can prevent the packet from making it to its destination. No connection establishment (which can add delay) Socket Overview Uniquely identified by an internet address, an end-to-end protocol (e.g. TCP or UDP) a port number Two types of (TCP/IP) sockets Stream sockets (e.g. uses TCP) provide reliable byte-stream service Datagram sockets (e.g. uses UDP) provide best-effort datagram service messages up to 65.500 bytes Socket extend the convectional UNIX I/O facilities file descriptors for network communication extended the read and write system calls Sockets Socket programming with UDP UDP: no connection between client and server no handshaking sender explicitly attaches IP address and port of destination to each packet server must extract IP address, port of sender from received packet UDP: transmitted data may be received out of order, or lost application viewpoint UDP provides unreliable transfer of groups of bytes ( datagrams ) between client and server UDP Ports 16-bit unsigned integers associated with UDP connection Used to distinguish different processes running on the same host Ports Proc1 Proc2 Proc3 Proc4 Proc5 A Internet B IP Address 1 IP Address 2 2
Four-step process for UDP sending data Send data to the remote device. Start a timer, set for a predetermined period of time. Wait for a response from the remote device. When it arrives, stop the timer and go on with your program. If the timer expires before you receive a response, go back and repeat step 1. After you have repeated step 1 a set number of times (the retry count) without an answer, assume that you cannot communicate with the remote host. To receive data Using UDP Sockets Create a UDP socket Create a local endpoint (Local IP + Local Port) Bind socket to the endpoint Receive data Close socket To send data Create a UDP socket Send data Close socket Connections between methods UdpClient For applications that require a connectionless socket, the UdpClient class provides a simple interface to UDP sockets. UDP is a connectionless protocol, so there is no such thing as a client or server; There are only UDP sockets either waiting for or sending data. You do not need to bind the UDP socket to a specific address and wait for incoming data. The C# API provides UDP streams by the following classes: Methods UdpClient - This class Provides User Datagram Protocol (UDP) network services. UdpClient Constructor: public UdpClient( AddressFamily family ); public UdpClient( int port ); public UdpClient( IPEndPoint localep ); public UdpClient( int port, AddressFamily family ); public UdpClient( string hostname, int port ); IPEndPoint: Initializes a new instance of the IPEndPoint class. public IPEndPoint( long address, int port ) public IPEndPoint( IPAddress address, int port ); void Connect(IPEndPoint remoteep) void Connect(IPAddress ip, int port) void Connect(String host, int port) public byte[] Receive(ref IPEndPoint remoteep) int Send(byte[] data, int size) int Send(byte[] data, int size, IPEndPoint remoteep) int Send(byte[] data, int size, string host, int port) void Close() Establishes a default remote host and default remote port. Returns a UDP datagram sent by a remote host. Sends a datagram to the client. The first version assumes a default remote end-point has been established. Closes the UDP connection. 3
Creating UDP Socket The following namespaces should be used Use new keyword to create an object of class Socket Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); Socket parameters The AddressFamily member specifies the addressing scheme that a socket instance must use to resolve an address. AddressFamily.InterNetwork indicates that an IP version 4 addresses is expected when a socket connects to an end point. The SocketType parameter specifies the socket type of the current instance. SocketType.Stream indicates a connection-oriented stream and SocketType.Dgram indicates a connectionless stream. The ProtocolType parameter specifies the protocol to be used for the communication. ProtocolType.Udp indicates that the protocol using is UDP. Creating Local Endpoint Resolve local IP addresses using functions Dns.Resolve() and Dns.GetHostName() Create an endpoint at the first IP address and port 11000 IPHostEntry hostentry = Dns.Resolve(Dns.GetHostName()); IPEndPoint endpoint = new IPEndPoint(hostEntry.AddressList[0], 11000); Binding Socket to Endpoint Make the socket wait for incoming data at the endpoint created previously s.bind(endpoint); Note: port number can be anything above 1023 UdpClient - receive The Receive() method allows you to receive data on the UDP port. There is no connection session established, so when a UDP port receives data, you do not necessarily know where it came from (unless you specified it in the UdpClient constructor). public byte[] Receive( ref IPEndPoint remoteep ); The Receive method uses the ref modifier to capture the IPEndPoint of the remote client. The local client has to first create a dummy IPEndPoint and then use it to call the Receive method. The Receive method will then replace the content of this dummy IPEndPoint with that of the remote client: Receiving Data Another endpoint is prepared to store remote endpoint information ReceiveFrom() will block until data is received IPEndPoint sender = new IPEndPoint(IPAddress.An EndPoint senderremote = (EndPoint)sender; byte[] msg = new Byte[256]; Console.WriteLine("Waiting for data..."); s.receivefrom(msg, ref senderremote); 4
UdpClient Send UdpClient: Send: Sends a UDP datagram to a remote host. The Send() method has three formats. If the UdpClient object references a remote host address and port, the Send() method does not need to specify the destination of the data. public int Send( byte[] dgram, int bytes); public int Send( byte[] dgram, int bytes, IPEndPoint endpoint ); public int Send( byte[] dgram, int bytes, string hostname, int port ); Sending Data Another endpoint is created to specify the receiver IP address and UDP port byte[] msg = Encoding.ASCII.GetBytes("This is a test"); Console.WriteLine("Sending data."); s.sendto(msg, new IPEndPoint(IPAddress.Parse("10.0.0.2"), 11000)); Closing Socket When no longer used, the socket must be closed s.close(); A Simple UDP Application UDP is a connectionless protocol. Therefore, the programmer must do only two things to make a server application ready to send or receive UDP packets: Create a Socket object Bind the socket to a local IPEndPoint After these two actions are taken, the socket can be used to either accept incoming UDP packets on the IPEndPoint, or send outgoing UDP packets to any other device on the network. The UDP Server Although UDP applications are not really servers or clients by strict definition, It creates a Socket object and binds it to a set IPEndPoint object so it can wait for incoming packets: IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050); Socket newsock = Socket(AddressFamily.InterNetwork, newsock.bind(ipep); Example of Server I class SimpleUdpServer IPEndPoint localep = new IPEndPoint(IPAddress.Any, 9050); UdpClient server = new UdpClient(localEP); Console.WriteLine("Waiting for a client..."); IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 0); //dummy IP byte[] data; while (true) data = server.receive(ref remoteep); Console.Write("Received from 0: ", remoteep.tostring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, data.length)); server.send(data, data.length, remoteep); 5
/* C# Network Programming by Richard Blum Publisher: Sybex ISBN: 0782141765 */ A UDP Client The UDP client program is similar to its partner server program. Because the client does not need to wait on a specific UDP port for incoming data, it does not use the Bind() method. Instead, it employs a random UDP port assigned by the system when the data is sent, and it uses the same port to receive return messages, so that both the server and client programs use the same port numbers. Simple Client I class SimpleUdpClient UdpClient client = new UdpClient("127.0.0.1", 9050); IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 0); byte[] data; string input; while (true) Console.Write("Enter message for server or exit to stop: "); client.send(encoding.ascii.getbytes(input), input.length); data = client.receive(ref remoteep); Console.Write("Echo Received from 0: ", remoteep.tostring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, data.length)); client.close(); public class SimpleUdpClient byte[] IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("127.0.0.1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork, EndPoint Remote = (EndPoint)sender; Simple Client II int recv = server.receivefrom(data, ref Remote); Console.WriteLine("Message received from 0:", Remote.ToS tring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, re cv)); while(true) server.sendto(encoding.ascii.getbytes(input), Remo te); recv = server.receivefrom(data, ref Remote); Distinguishing UDP Messages One of the best features of UDP is that it addresses the TCP difficulty of handling messages without honoring their boundaries. UDP preserves the message boundaries of all sent messages. Each ReceiveFrom() method call will read only the data sent as a result of a single SendTo() method call. Recall that a UDP socket, once it s created, can receive messages from any UDP client. For the UDP socket to distinguish which client sent which data, it is imperative that each message be self-contained in a single packet and marked with the sending device s IP information. This allows the receiving device to identify both message and sender. Test Udp Server class TestUdpSrvr int recv; byte[] IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050); Socket newsock = new Socket(AddressFamily.InterNetwork, newsock.bind(ipep); Console.WriteLine("Waiting for a client..."); EndPoint tmpremote = (EndPoint)(sender); recv = newsock.receivefrom(data, ref tmpremote); Console.WriteLine("Message received from 0:", tmpremote.tostring()); Console.WriteLine(Encoding.ASCII.GetSt ring(data, 0, recv)); string welcome = "Welcome to my test server"; data = Encoding.ASCII.GetBytes(welcome); newsock.sendto(data, data.length, SocketFlags.None, tmpremote); for (int i = 0; i < 5; i++) recv = newsock.receivefrom(data, ref tmpremote); Console.WriteLine(Encoding.ASCII.GetSt ring(data, 0, recv)); newsock.close(); The result of the program TestUdpSrvr binds a UDP socket to the 9050 port and waits for a client to connect with a greeting message. When this happens, the server sends back a welcome banner and then attempts to receive five messages in a row from the client. 6
Test Udp Client public class TestUdpClient byte[] IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork, EndPoint tmpremote = (EndPoint)sender; int recv = server.receivefrom(data, ref tmpremote); Console.WriteLine("Message received from 0:", tmpremote.tostring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); server.sendto(encoding.ascii.getbytes("message 1"), tmpremote); server.sendto(encoding.ascii.getbytes("message 2"), tmpremote); server.sendto(encoding.ascii.getbytes("message 3"), tmpremote); server.sendto(encoding.ascii.getbytes("message 4"), tmpremote); server.sendto(encoding.ascii.getbytes("message 5"), tmpremote); // Multi-Send public class UdpClientMultiSend UdpClient sock = new UdpClient(); IPEndPoint iep = new IPEndPoint(IPAddress. Parse("127.0.0.1"), 9050); byte[] data = Encoding.ASCII.GetBytes("Thi s is a test message"); sock.send(data, data.length, iep); sock.close(); Multi-Send/Recv // Multi-Recv public class UdpClientMultiRecv UdpClient sock = new UdpClient(9050); Console.WriteLine("Ready to receive..."); sock.joinmulticastgroup(ipaddress.parse("127.0.0.1 "), 9050); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); byte[] data = sock.receive(ref iep); string stringdata = Encoding.ASCII.GetString(data, 0, dat a.length); Console.WriteLine("received: 0 from: 1", stringdata, i ep.tostring()); sock.close(); When UDP Goes Bad While solving the message boundary problem found in TCP communications, UDP introduces some other predicaments that programmers must deal with in UDP programs: Lost data as a result of how the ReceiveFrom() method works Detecting and allowing for lost packets These two UDP issues often cause unexpected dilemmas for network programmers who are more accustomed to working with TCP communications, and you must take them into consideration when creating production-quality UDP applications. class BadUdpClient byte[] data = new byte[30]; IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("127.0.0.1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork, server.sendto(data, data.length, SocketFlags.None, ipep); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint tmpremote = (EndPoint)sender; data = new byte[30]; int recv = server.receivefrom(data, ref tmpremote); Udp BadClient Console.WriteLine("Message received from 0:", tmpremote.tostring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); while (true) server.sendto(encoding.ascii.getbytes(input), tmpremote); data = new byte[30]; recv = server.receivefrom(data, ref tmpremote); stringdata = Encoding.ASCII.GetString(data, 0, recv); Result of the UdpBad C:\>BadUdpClient Message received from 127.0.0.1:9050: Welcome to my test server test message test message longer test message longer test message This is an even longer test message Unhandled Exception: System.Net.Sockets.SocketException: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketflags, EndPoint& remoteep) at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, EndPoint& remoteep) at BadUdpClient.Main() C:\> BetterUdpClient int i = 30; while (true) class BetterdUdpClient server.sendto(encoding.ascii.getbytes(input), tmpremote); data = new byte[i]; try byte[] data = new byte[30]; recv = server.receivefrom(data, ref tmpremote); IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("127.0.0.1"), 9050); catch (SocketException) Socket server = new Socket(AddressFamily.InterNetwork, Console.WriteLine("WARNING: data lost, retry message."); i += 10; EndPoint tmpremote = (EndPoint)sender; data = new byte[30]; int recv = server.receivefrom(data, ref tmpremote); Console.WriteLine("Message received from 0:", tmpremote.tostring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); 7
public class BestUdpClient private static byte[] private static private static EndPoint Remote = (EndPoint)sender; private static int size = 30; BestUdpClient- II private static int AdvSndRcvData(Socket s, byte[] message, EndPoint rmtde vice) int recv = 0; int retry = 0; while (true) Console.WriteLine("Attempt #0", retry); try s.sendto(message, message.length, SocketFlags.None, rmtdevice); data = new byte[size]; recv = s.receivefrom(data, ref Remote); catch (SocketException e) if (e.errorcode == 10054) recv = 0; else if (e.errorcode == 10040) Console.WriteLine("Error receiving packet"); size += 10; recv = 0; if (recv > 0) return recv; else retry++; if (retry > 4) return 0; int recv; IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("127.0.0.1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork, int sockopt = (int)server.getsocketoption(socketoptionlevel.socket, Soc ketoptionname.receivetimeout); Console.WriteLine("Default timeout: 0", sockopt); server.setsocketoption(socketoptionlevel.socket, SocketOptionName.R eceivetimeout, 3000); sockopt = (int)server.getsocketoption(socketoptionlevel.socket, Socket OptionName.ReceiveTimeout); Console.WriteLine("New timeout: 0", sockopt); recv = AdvSndRcvData(server, data, ipep); if (recv > 0) else Console.WriteLine("Unable to communicate with remote host"); return; while(true) recv = AdvSndRcvData(server, Encoding.ASCII.GetBytes(input), ipep); if (recv > 0) else Console.WriteLine("Did not receive an answer"); Preventing Lost Packets The other difficult task often encountered with UDP communications is providing for the possibility of lost packets. Because UDP is a connectionless protocol, there is no way for a device to know if a packet it sends actually made it to the remote device. Many games, for instance, use UDP packets to transmit positional information for players in the game. Every few seconds, a player s position and game status are transmitted to other players in the game. If a packet is lost in the network, an updated one will automatically be sent a few seconds later. Using Socket Time-outs Time out Udp Client The ReceiveFrom() method is a blocking function. It will block execution of the program until it receives a data packet. This is a Very Bad Thing in UDP programs because you are not guaranteed to receive a packet. The format of the SetSocketOption() method is as follows: SetSocketOption(SocketOptionLevel so, SocketOptionName sn, int value) The SocketOptionLevel specifies what type of socket option to implement. The SocketOptionName defines the specific option to set, and the last parameter (int value) indicates the set value for the option. /* C# Network Programming by Richard Blum Publisher: Sybex ISBN: 0782141765 */ public class TimeoutUdpClient byte[] int recv; IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,Pro tocoltype.udp); int sockopt = (int)server.getsocketoption(socketoptionlevel.socket,soc ketoptionname.receivetimeout); Console.WriteLine("Default timeout: 0", sockopt); server.setsocketoption(socketoptionlevel.socket, SocketOptionName.ReceiveTimeout, 3000); sockopt = (int)server.getsocketoption(socketoptionlevel.socket, SocketOptionName.ReceiveTimeout); Console.WriteLine("New timeout: 0", sockopt); EndPoint tmpremote = (EndPoint)sender; recv = server.receivefrom(data, ref tmpremote); Console.WriteLine("Message received from 0:", tmpremote.tostring()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); while (true) server.sendto(encoding.ascii.getbytes(input), tmpremote); recv = server.receivefrom(data, ref tmpremote); Catching the Exception Exceptions Now that you know the socket will produce a SocketException When the time-out is reached, you need only to catch the Exception so you can gracefully inform the customer about it and allow some alternatives to the application /* C# NetworkProgramming by Richard Blum Publisher: Sybex ISBN: 0782141765 */ public class ExceptionUdpClient byte[] int recv; IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("127.0.0. 1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork, Soc kettype.dgram, ProtocolType.Udp); int sockopt = (int)server.getsocketoption(socketoptionlevel.soc ket, SocketOptionName.ReceiveTimeout); Console.WriteLine("Default timeout: 0", sockopt); server.setsocketoption(socketoptionlevel.socket, SocketOptio nname.receivetimeout, 3000); sockopt = (int)server.getsocketoption(socketoptionlevel.socke t, SocketOptionName.ReceiveTimeout); Console.WriteLine("New timeout: 0", sockopt); EndPoint Remote = (EndPoint)sender; try recv = server.receivefrom(data, ref Remote); Console.WriteLine("Message received from 0:", Remote. ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, rec v)); catch (SocketException) Console.WriteLine("Problemcommunicating with remote server"); return; while(true) server.sendto(encoding.ascii.getbytes(input), ipep); try recv = server.receivefrom(data, ref Remote); catch (SocketException) Console.WriteLine("Error receiving message"); 8