1 Appendix C C NETWORKING After studying this appendix you should have a basic vocabulary about networking you should be able to develop a basic communication system using UDP. Copyright © 2014 P.J. Blignaut Appendix C 2 Networking Networking Basics Acknowledgement: The text in this section was taken from Wikipedia Protocols In telecommunications, a communication protocol is a system of rules that allow two or more entities of a communications system to transmit information. These rules define the syntax, semantics and synchronization of communication and possible error recovery methods. Protocols may be implemented by hardware, software, or a combination of both. Communication protocols have to be agreed upon by the parties involved. To reach agreement, a protocol may be developed into a technical standard. Systems typically do not use a single protocol to handle a transmission. Instead they use a set of cooperating protocols, sometimes called a protocol family or protocol suite. Some of the best known protocol suites include: IPX/SPX, X.25, AX.25, AppleTalk and TCP/IP. To implement a networking protocol, the protocol software modules are interfaced with a framework implemented on the machine's operating system. This framework implements the networking functionality of the operating system. The best known frameworks are the TCP/IP model and the OSI model. The Internet Protocol (IP) is the principal communication protocol in the Internet protocol suite for relaying datagrams across network boundaries. Its routing function enables internetworking, and essentially establishes the Internet. IP has the task of delivering packets from the source host to the destination host solely based on the IP addresses in the packet headers. For this purpose, IP defines packet structures that encapsulate the data to be delivered. It also defines addressing methods that are used to label the datagram with source and destination information. The first major version of IP, Internet Protocol Version 4 (IPv4), is the dominant protocol of the Internet. Its successor is Internet Protocol Version 6 (IPv6). Connectionless communication In connection-oriented communication the communicating peers must first establish a logical or physical data channel or connection in a dialog preceding the exchange of user data. Connectionless communication, on the other hand, is a data transmission method by which each data unit is individually addressed and routed based on information carried in each unit, rather than in the setup information of a prearranged, fixed data channel as in connection-oriented communication. Connectionless communication is often referred to as CL-mode communication. Under connectionless communication between two network end points, a message can be sent from one end point to another without prior arrangement. The device at one end of the communication transmits data addressed to the other, without first ensuring that the recipient is available and ready to receive the data. Some protocols allow for error correction by requested retransmission. Internet Protocol (IP) and User Datagram Protocol (UDP) are connectionless protocols. The connectionless communications has the advantage over connection-oriented communications in that it has low overhead. It also allows for multicast (more than one listener specified) and broadcast (unspecified) operations in which the same data is transmitted to several recipients in a single transmission. Connectionless protocols are usually described as stateless protocols because the end points have no protocol-defined way to remember where they are in a "conversation" of message exchanges. In connectionless transmissions the service provider usually cannot guarantee that there will be no loss, error insertion, duplication, or out-of-sequence delivery of the packet. However, the effect of errors may be reduced by implementing error correction within an application protocol. Error checking A checksum is a small field from a block of digital data for the purpose of detecting errors which may have been introduced during its transmission or storage. Checksums are generated through a checksum function or checksum algorithm on both ends of the transmission. A good checksum algorithm will usually output a significantly different value, even for small changes made to the input. If the computed checksum on Copyright © 2014 P.J. Blignaut Appendix C 3 Networking the receiving end matches the stored value on the transmission end, there is a very high probability the data has not been accidentally altered or corrupted. Check digits and parity bits are special cases of checksums, appropriate for small blocks of data (such as ID numbers, bank account numbers, computer words, single bytes, etc.). Handshaking is an automated process of negotiation that dynamically sets parameters of a communications channel established between two entities before normal communication over the channel begins. It follows the physical establishment of the channel and precedes normal information transfer. It is usually a process that takes place when a computer is about to communicate with a foreign device to establish rules for communication. When a computer communicates with another device like a modem, printer, or network server, it needs to handshake with it to establish a connection. A simple handshaking protocol might only involve the receiver sending a message meaning "I received your last message and I am ready for you to send me another one." A more complex handshaking protocol might allow the sender to ask the receiver if he is ready to receive or for the receiver to reply with a negative acknowledgement meaning "I did not receive your last message correctly, please resend it" (e.g. if the data was corrupted en route). The TCP/IP three-way handshake IP Address An Internet Protocol address (IP address) is a numerical label assigned to each device (e.g., computer, printer) participating in a computer network that uses the Internet Protocol for communication. An IP address serves two principal functions: host or network interface identification and location addressing. The designers of the Internet Protocol defined an IP address as a 32-bit number and this system, known as Internet Protocol Version 4 (IPv4), is still in use today. However, because of the growth of the Internet and the predicted depletion of available addresses, a new version of IP (IPv6), using 128 bits for the address, was developed in 1995. IP addresses are usually written and displayed in human-readable notations, such as 172.16.254.1 (IPv4), and 2001:db8:0:1234:0:567:8:1 (IPv6). Ports A port serves as an endpoint for many types of communication. It is not a hardware device, but a logical construct that identifies a service or process. A port is always associated with an IP address of a host and the protocol type of the communication, and thus completes the destination or origination address of a communications session. A port is identified for each address and protocol by a 16-bit number, commonly known as the port number. Specific port numbers are often used to identify specific services. Of the thousands of enumerated ports, 1024 well-known port numbers are reserved by convention to identify specific service types on a host. Socket A network socket is an endpoint of an inter-process communication across a computer network. Today, most communication between computers is based on the Internet Protocol; therefore most network sockets are Internet sockets. Copyright © 2014 P.J. Blignaut Appendix C 4 Networking A socket API is an application programming interface (API), usually provided by the operating system, that allows application programs to control and use network sockets. Internet socket APIs are usually based on the Berkeley sockets standard. A socket address is the combination of an IP address and a port number, much like one end of a telephone connection is the combination of a phone number and a particular extension. Based on this address, internet sockets deliver incoming data packets to the appropriate application process or thread. Datagram A packet transmitted in a connectionless mode is frequently called a datagram. The delivery, arrival time, and order of arrival need not be guaranteed by the network. It is a “self-contained, independent entity of data carrying sufficient information to be routed from the source to the destination computer without reliance on earlier exchanges between this source and destination computer and the transporting network” (RFC 1594). Each datagram has two components, a header and a data payload. The header contains all the information sufficient for routing from the originating equipment to the destination without relying on prior exchanges between the equipment and the network. Headers may include source and destination addresses as well as a type field. The payload is the data to be transported. UDP The User Datagram Protocol (UDP) is one of the core members of the Internet protocol suite. The protocol was designed by David P. Reed in 1980 and formally defined in RFC 768. UDP uses a simple connectionless transmission model with a minimum of protocol mechanism. It has no handshaking dialogues, and thus exposes any unreliability of the underlying network protocol to the user's program. There is no guarantee of delivery, ordering, or duplicate protection. UDP provides checksums for data integrity, and port numbers for addressing different functions at the source and destination of the datagram (Wikipedia). With UDP, computer applications can send messages in the form of datagrams to other hosts on an Internet Protocol (IP) network without prior communications to set up special transmission channels or data paths (i.e. connectionless). UDP is suitable for purposes where error checking and correction is either not necessary or is performed in the application, avoiding the overhead of such processing at the network interface level. Time-sensitive applications often use UDP because dropping packets is preferable to waiting for delayed packets, which may not be an option in a real-time system. If error correction facilities are needed at the network interface level, an application may use the Transmission Control Protocol (TCP) or Stream Control Transmission Protocol (SCTP) which are designed for this purpose. Threading A thread of execution is the smallest sequence of programmed instructions that can be managed independently. Multiple threads can exist within the same process, executing concurrently (one starting before others finish) and share resources such as memory. On a single processor, multithreading is generally implemented by time slicing (as in multitasking), and the central processing unit (CPU) switches between different software threads. This generally happens frequently enough that the user perceives the threads or tasks as running at the same time (in parallel). On a multiprocessor or multi-core system, multiple threads can be executed in parallel (at the same instant), with every processor or core executing a separate thread simultaneously. Make Your Hands Dirty We will develop a Visual Studio solution with three different executables. Eventually, we will have a Talker.exe, Listener.exe and DataStructures.dll. The roles of the Talker and Listener are obvious. The DataStructures.dll will provide us with classes that can be used to encapsulate an object on both the sending and receiving ends. Copyright © 2014 P.J. Blignaut Appendix C 5 Networking The Talker (Sender of a message) Start with a new Windows Forms project. Put a rich text box and two buttons on the form as in the screen print. Enter the following code for the Send button: private void btnSendMessage_Click(object sender, EventArgs e) { //Create socket Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPAddress sendToIP = IPAddress.Parse("192.168.3.255"); IPEndPoint endPoint = new IPEndPoint(sendToIP, 2000); //Serialize any object, convert to byte[] and send MemoryStream strm = new MemoryStream(); IFormatter formatter = new BinaryFormatter(); formatter.Serialize(strm, rtbMessage.Text); socket.SendTo(strm.ToArray(), endPoint); socket.Close(); } //btnSendMessage_Click Things to understand The Socket object defines the protocol (UDP) and the type of packet that we will send (datagram). We need to specify an IP endpoint (IP address + port) of the destination of the message. Specifying 255 in the last position of the IP means that the message will be broadcasted to all IPs in the range. Revisit the basics of serialization in Chapter 13. We now use a MemoryStream instead of a FileStream and serialize the text message into it. Lastly, the serialized message is sent to any listener within the IP rage who is listening at the time. Note that the SendTo method always sends data as an array of bytes. Therefore, we need to cast the data to byte[]. Clear the message on both ends With some innovation, we can clear the message on both ends. We can, for example, send a special marker string. When received, the listener will know what to do with it: Replace the Serialize method call in the listing above with the following: formatter.Serialize(strm, “Clear message”); Copyright © 2014 P.J. Blignaut Appendix C 6 Networking The Listener (Receiver of a message) Start with a new Windows Forms project. Put a label on the form as in the screen print. Declare a bool flag, isListening, and a UdpClient object, listener, as data members in the form class: public partial class CfrmListener : Form { private bool isListening = false; private UdpClient listener; Enter the following code for the Shown method handler of the form: private void CfrmListener_Shown(object sender, EventArgs e) { new Thread(ListenForMessage).Start(); } //CfrmListener_Shown Add the method to listen for messages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //Listen in separate thread private void ListenForMessage() { //Set up listener int listenPort = 2000; isListening = true; listener = new UdpClient(listenPort); IPEndPoint endPointIP = new IPEndPoint(IPAddress.Any, listenPort); //Listening loop while (isListening) { try { //Blocking call - execution will block here until a message is received byte[] bytesReceived = listener.Receive(ref endPointIP); //Check if form exists if (this.IsHandleCreated) { //We need to access the UI from another thread (lblMessage) this.BeginInvoke((MethodInvoker)delegate() { //Put bytes received in memory stream MemoryStream strm = new MemoryStream(); strm.Write(bytesReceived, 0, bytesReceived.Length); strm.Seek(0, SeekOrigin.Begin); //Deserialize the stream IFormatter formatter = new BinaryFormatter(); object obj = formatter.Deserialize(strm); strm.Close(); Copyright © 2014 P.J. Blignaut Appendix C 17 18 19 20 21 22 23 7 Networking //Handle the message if (obj.ToString() == "Clear message") lblMessage.Text = ""; else lblMessage.Text = obj.ToString(); //Ensure that the UI is updated before the thread is terminated Application.DoEvents(); }); //Terminate UI thread } //if } //try catch (SocketException ex) { MessageBox.Show("Stop listening."); } } //while (isListening) } //Listen Stop listening. Add the following code for the form’s FormClosed event handler: private void CfrmListener_FormClosed(object sender, FormClosedEventArgs e) { isListening = false; listener.Close(); } //CfrmListener_FormClosed Understand what you are doing We start listening for incoming messages as soon as the form is shown on the desktop. It is important to understand that the listener.Receive method in line 8 is a blocking method. That means that execution stops at line 8 until a message is received. This will stop handling of all events in the same thread. If the blocking method call in line 8 were called from the same thread as that of the user interface, the program will become unresponsive. Therefore, we had to start a new thread of execution in the Shown method handler of the form so that the user can still work in the program while waiting for messages is done on a separate thread in the background. Instantiate and prepare the listener object in lines 2 – 4. The port must be the same as in the talker’s code. We also have to define an IPEndPoint to identify the sender’s IP. Line 6 starts a loop that will continue to listen for messages as long as the isListening flag is true. The try … catch in lines 7-23 is necessary to handle the change of isListening from true to false in a graceful way. Remember that the waiting loop for messages runs on another thread as that of the user interface. Since we want to write the message that was received in line 8 to a label on the user interface (so called crossthread operation), we have to temporarily jump out of the current thread to write the message in lines 18 or 20. This can be done by calling the BeginInvoke method of the current user interface object, the form, in line 10. We use a memory stream in lines 11 - 16 to save the byte array of the message that was received in line 8. Since we know that the byte array originated from a character string in the Talker program, we can cast the object returned by the Deserialize method to a string and handle it in lines 17 – 20. It is essential that the UI is updated before the temporary execution of the UI thread is terminated in line 21. Note the way in which the special marker string to clear the message is handled in lines 17-18. The isListening flag is changed to false and the listener closed when the form is closed, Copyright © 2014 P.J. Blignaut Appendix C 8 Networking Communication of objects Start with a new Class library project. Name it Classes.cs. Add the following class to the library. Not that this is a very basic class that is used to illustrate the priciple and that you will hardly ever encounter such a basic class. namespace Classes { [System.Serializable] public class CBook { public string Author { get; set; } public string Title { get; set; } } } Compile the class (press on F6 Build). Go back to the Talker and Listener programs and include the Classes.dll as reference in both of them. (Right-click on References in the Solution explorer, click “Add Reference…”, browse to Classes.dll and click Add.) Also add the using directive to both the Talker and Listener programs. using Classes; Add two text boxes and a Send object button the talker’s form as indicated. Enter the following code for the Send object button: private void btnSendObject_Click(object sender, EventArgs e) { //Create object CBook book = new CBook { Title = txtTitle.Text, Author = txtAuthor.Text }; //Create socket Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPAddress sendToIP = IPAddress.Parse("192.168.3.255"); IPEndPoint endPoint = new IPEndPoint(sendToIP, 2001); //Serialize object, convert to byte[] and send MemoryStream strm = new MemoryStream(); new BinaryFormatter().Serialize(strm, book); socket.SendTo(strm.ToArray(), endPoint); strm.Close(); socket.Close(); } //btnSendObject_Click Copyright © 2014 P.J. Blignaut Appendix C 9 Networking Change the ListenForMessage method in the Listener program as follows: 1 2 3 4 5 6 7 8 private void ListenForMessage() { //Set up listener int listenPort = 2000; isListening = true; listener = new UdpClient(listenPort); IPEndPoint endPointIP = new IPEndPoint(IPAddress.Any, listenPort); //Listening loop while (isListening) { try { //Blocking call - execution will block here until a message is received byte[] bytesReceived = listener.Receive(ref endPointIP); 9 10 11 //Put bytes received in memory stream MemoryStream strm = new MemoryStream(); strm.Write(bytesReceived, 0, bytesReceived.Length); strm.Seek(0, SeekOrigin.Begin); 12 13 14 //Deserialize the stream IFormatter formatter = new BinaryFormatter(); CBook book = (CBook)formatter.Deserialize(strm); strm.Close(); 17 18 19 20 //Handle the message string s= “Title: “ + book.Title + “\nAuthor: ” + book.Author; MessageBox.Show(s) } //try catch (SocketException ex) { MessageBox.Show("Stop listening."); } } //while (isListening) } //Listen If all is fine, you should be able to enter data in the fields on the sender’s side, click on the button to send the object and a message box with the book details should pop up on the receiver’s side. Understand what you are doing Since serialization can be done on any object, we can create a byte array of any object and send it over a network. It is important that the data structure is known to both sender and receiver and therefore we had to create a separate dll with the data structure and reference it from both the sender and the receiver. On the receiver’s side, we can deserialize the object and cast it to the appropriate class. Note that, since we don’t access the user interface directly, we don’t have to check for the form’s existence or jump to the UI thread. Copyright © 2014 P.J. Blignaut Appendix C 10 Networking Keywords Make sure that you know what each of these items mean or where they are used. Blocking method Check digits Checksums Connection-oriented communication Connectionless communication Datagram Deserialize Error checking Handshaking Internet Protocol (IP) IP Address Protocol Serialize Copyright © 2014 P.J. Blignaut Socket Stateless protocols Parity bit Port TCP TCP/IP UDP