1. Trang chủ
  2. » Công Nghệ Thông Tin

Network Programming in .NET With C# and Visual Basic .NET phần 6 docx

56 722 1

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 56
Dung lượng 618,09 KB

Nội dung

10.7 Avoiding deadlocks 261 Chapter 10 The lock (or syncLock ) is required for application stability. If two threads repeatedly access the same user interface element at the same time, the application’s UI becomes unresponsive. Finally, the threading namespace is required: C# using System.Threading; VB.NET imports System.Threading To test the application, run it from Visual Studio .NET and wait for a minute or two for the increments-per-second value to settle on a number (Figure 10.1). You can experiment with this application and see how perfor- mance increases and decreases under certain conditions, such as running several applications or running with low memory. 10.7 Avoiding deadlocks Deadlocks are the computing equivalent of a Catch-22 situation. Imagine an application that retrieves data from a Web site and stores it in a database. Users can use this application to query from either the database or the Web site. These three tasks would be implemented as separate threads, and for whatever reason, no two threads can access the Web site or the database at the same time. The first thread would be:  Wait for access to the Web site.  Restrict other threads’ access to the Web site.  Wait for access to the database. Figure 10.1 Thread pool sample application. 262 10.8 Load balancing  Restrict other threads’ access to the database.  Draw down the data, and write it to the database.  Relinquish the restriction on the database and Web site. The second thread would be:  Wait for access to the database.  Restrict other threads’ access to the database.  Read from the database.  Execute thread three, and wait for its completion.  Relinquish the restriction on the database. The third thread would be:  Wait for access to the Web site.  Restrict other threads’ access to the Web site.  Read from the Web site.  Relinquish the restriction on the Web site. Any thread running on its own will complete without any errors; how- ever, if thread 2 is at the point of reading from the database, while thread 1 is waiting for access to the database, the threads will hang. Thread 3 will never complete because thread 1 will never get access to the database until thread 2 is satisfied that thread 3 is complete. A deadlock could have been avoided by relinquishing the database restriction before executing thread 3, or in several different ways, but the problem with deadlocks is spotting them and redesigning the threading structure to avoid the bug. 10.8 Load balancing Load balancing is a means of dividing workload among multiple servers by forwarding only a percentage of requests to each server. The simplest way of doing this is DNS round-robin, which is where a DNS server contains multiple entries for the same IP address. So when a client requests a DNS, it will receive one of a number of IP addresses to connect to. This 10.8 Load balancing 263 Chapter 10 approach has one major drawback in that if one of your servers crashes, 50% of your clients will receive no data. The same effect can be achieved on the client side, where the application will connect to an alternative IP address if one server fails to return data. Of course, this would be a night- mare scenario if you deploye a thousand kiosks, only to find a week later that your service provider had gone bust and you were issued new IP addresses. If you work by DNS names, you will have to wait 24 hours for the propagation to take place. Computers can change their IP addresses by themselves, by simply returning a different response when they receive an ARP request. There is no programmatic control over the ARP table in Windows computers, but you can use specially designed load-balancing software, such as Microsoft Network Load Balancing Service (NLBS), which ships with the Windows 2000 advanced server. This allows many computers to operate from the same IP address. By way of checking the status of services such as IIS on each computer in a cluster, every other computer can elect to exclude that computer from the cluster until it fixes itself, or a technician does so. The computers do not actually use the same IP address; in truth, the IP addresses are interchanged to create the same effect. NLBS is suitable for small clusters of four or five servers, but for high- end server farms from between 10 and 8,000 computers, the ideal solution is a hardware virtual server, such as Cisco’s Local Director. This machine sits between the router and the server farm. All requests to it are fed directly to one of the 8,000 computers sitting behind it, provided that that server is lis- tening on port 80. None of the above solutions—DNS round-robin, Cisco Local Director, or Microsoft NLBS—can provide the flexibility of custom load balancing. NLBS, for instance, routes requests only on the basis of a percentage of the client requests they will receive. So if you have multiple servers with differ- ent hardware configurations, it’s your responsibility to estimate each sys- tem’s performance compared to the others. Therefore, if you wanted to route a percentage of requests based on actual server CPU usage, you couldn’t achieve this with NLBS alone. There are two ways of providing custom load balancing, either through hardware or software. A hardware solution can be achieved with a little imagination and a router. Most routers are configurable via a Web interface or serial connection. Therefore, a computer can configure its own router either through an RS232 connection (briefly described in Chapter 4) or by using HTTP. Each computer can periodically connect to the router and set up port forwarding so that incoming requests come to it rather than the 264 10.8 Load balancing other machine. The hardware characteristics of the router may determine how quickly port forwarding can be switched between computers and how requests are handled during settings changes. This method may require some experimentation, but it could be a cheap solution to load balancing, or at least to graceful failover. Custom software load balancers are applicable in systems where the time to process each client request is substantially greater than the time to move the data across the network. For these systems, it is worth considering using a second server to share the processing load. You could program the clients to connect to switch intermittently between servers, but this may not always be possible if the client software is already deployed. A software load balancer would inevitably incur an overhead, which in some cases could be more than the time saved by relieving server load. Therefore, this solution may not be ideal in all situations. This implementation of a software load balancer behaves a little like a proxy server. It accepts requests from the Internet and relays them to a server of its choosing. The relayed requests must have their HOST header changed to reflect the new target. Otherwise, the server may reject the request. The load balancer can relay requests based on any criteria, such as server CPU load, memory usage, or any other factor. It could also be used to control failover, where if one server fails, the load balancer could auto- matically redirect traffic to the remaining operational servers. In this case, a simple round-robin approach is used. The example program balances load among three mirrored HTTP serv- ers: uk.php.net, ca.php.net, and ca2.php.net. Requests from users are directed initially to the load-balancing server and are then channeled to one of these servers, with the response returned to the user. Note that this approach does not take advantage of any geographic proximity the user may have to the Web servers because all traffic is channeled through the load balancer. To create this application, start a new project in Microsoft Visual Studio .NET. Draw a textbox on the form, named tbStatus. It should be set with multiline to true. Add two public variables at the top of the Form class as shown. The port variable is used to hold the TCP port on which the load balancer will listen. The site variable is used to hold a number indicating the next available Web server. C# public class Form1 : System.Windows.Forms.Form 10.8 Load balancing 265 Chapter 10 { public int port; public int site; VB.NET Public Class Form1 Inherits System.Windows.Forms.Form Public port As Integer Public Shadows site As Integer When the application starts, it will immediately run a thread that will wait indefinitely for external TCP connections. This code is placed into the form’s Load event: C# private void Form1_Load(object sender, System.EventArgs e) { Thread thread = new Thread(new ThreadStart(ListenerThread)); thread.Start(); } VB.NET Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim thread As Thread = New Thread(New ThreadStart( _ AddressOf ListenerThread)) thread.Start() End Sub The ListenerThread works by listening on port 8889 and waiting on connections. When it receives a connection, it instantiates a new instance of the WebProxy class and starts its run method in a new thread. It sets the class’s clientSocket and UserInterface properties so that the WebProxy instance can reference the form and the socket containing the client request. C# public void ListenerThread() { 266 10.8 Load balancing port = 8889; TcpListener tcplistener = new TcpListener(port); reportMessage("Listening on port " + port); tcplistener.Start(); while(true) { WebProxy webproxy = new WebProxy(); webproxy.UserInterface = this; webproxy.clientSocket = tcplistener.AcceptSocket(); reportMessage("New client"); Thread thread = new Thread(new ThreadStart(webproxy.run)); thread.Start(); } } VB.NET Public Sub ListenerThread() port = 8889 Dim tcplistener As TcpListener = New TcpListener(port) reportMessage("Listening on port " + port.ToString()) tcplistener.Start() Do Dim webproxy As WebProxy = New WebProxy webproxy.UserInterface = Me webproxy.clientSocket = tcplistener.AcceptSocket() reportMessage("New client") Dim thread As Thread = New Thread(New ThreadStart( _ AddressOf webproxy.run)) thread.Start() Loop End Sub A utility function that is used throughout the application is reportMes- sage . Its function is to display messages in the textbox and scroll the textbox automatically, so that the user can see the newest messages as they arrive. C# public void reportMessage(string msg) { lock(this) 10.8 Load balancing 267 Chapter 10 { tbStatus.Text += msg + "\r\n"; tbStatus.SelectionStart = tbStatus.Text.Length; tbStatus.ScrollToCaret(); } } VB.NET Public Sub reportMessage(ByVal msg As String) SyncLock Me tbStatus.Text += msg + vbCrLf tbStatus.SelectionStart = tbStatus.Text.Length tbStatus.ScrollToCaret() End SyncLock End Sub The core algorithm of the load balancer is held in the getMirror func- tion. This method simply returns a URL based on the site variable. More complex load-balancing techniques could be implemented within this func- tion if required. C# public string getMirror() { string Mirror = ""; switch(site) { case 0: Mirror="uk.php.net"; site++; break; case 1: Mirror="ca.php.net"; site++; break; case 2: Mirror="ca2.php.net"; site=0; break; } return Mirror; } 268 10.8 Load balancing VB.NET Public Function getMirror() As String Dim Mirror As String = "" Select Case site Case 0 Mirror = "uk.php.net" site = site + 1 Case 1 Mirror = "ca.php.net" site = site + 1 Case 2 Mirror = "ca2.php.net" site = 0 End Select Return Mirror End Function The next step is to develop the WebProxy class. This class contains two public variables and two functions. Create the class thus: C# public class WebProxy { public Socket clientSocket; public Form1 UserInterface; } VB.NET Public Class WebProxy Public clientSocket As Socket Public UserInterface As Form1 End Class The entry point to the class is the run method. This method reads 1,024 (or fewer) bytes from the HTTP request. It is assumed that the HTTP request is less than 1 Kb in size, in ASCII format, and that it can be received in one Receive operation. The next step is to remove the HOST HTTP header and replace it with a HOST header pointing to the server returned by getMirror. Having done this, it passes control to relayTCP to complete the task of transferring data from user to Web server. 10.8 Load balancing 269 Chapter 10 C# public void run() { string sURL = UserInterface.getMirror(); byte[] readIn = new byte[1024]; int bytes = clientSocket.Receive(readIn); string clientmessage = Encoding.ASCII.GetString(readIn); clientmessage = clientmessage.Substring(0,bytes); int posHost = clientmessage.IndexOf("Host:"); int posEndOfLine = clientmessage.IndexOf("\r\n",posHost); clientmessage = clientmessage.Remove(posHost,posEndOfLine-posHost); clientmessage = clientmessage.Insert(posHost,"Host: "+ sURL); readIn = Encoding.ASCII.GetBytes(clientmessage); if(bytes == 0) return; UserInterface.reportMessage("Connection from:" + clientSocket.RemoteEndPoint + "\r\n"); UserInterface.reportMessage ("Connecting to Site:" + sURL + "\r\n"); relayTCP(sURL,80,clientmessage); clientSocket.Close(); } VB.NET Public Sub run() Dim sURL As String = UserInterface.getMirror() Dim readIn() As Byte = New Byte(1024) {} Dim bytes As Integer = clientSocket.Receive(readIn) Dim clientmessage As String = _ Encoding.ASCII.GetString(readIn) clientmessage = clientmessage.Substring(0, bytes) Dim posHost As Integer = clientmessage.IndexOf("Host:") Dim posEndOfLine As Integer = clientmessage.IndexOf _ (vbCrLf, posHost) clientmessage = clientmessage.Remove(posHost, _ posEndOfLine - posHost) clientmessage = clientmessage.Insert(posHost, _ "Host: " + sURL) readIn = Encoding.ASCII.GetBytes(clientmessage) If bytes = 0 Then Return 270 10.8 Load balancing UserInterface.reportMessage("Connection from:" + _ clientSocket.RemoteEndPoint.ToString()) UserInterface.reportMessage("Connecting to Site:" + sURL) relayTCP(sURL, 80, clientmessage) clientSocket.Close() End Sub The data transfer takes place on relayTCP. It opens a TCP connection to the Web server on port 80 and then sends it the modified HTTP header sent from the user. Immediately after the data is sent, it goes into a loop, reading 256-byte chunks of data from the Web server and sending it back to the client. If at any point it encounters an error, or the data flow comes to an end, the loop is broken and the function returns. C# public void relayTCP(string host,int port,string cmd) { byte[] szData; byte[] RecvBytes = new byte[Byte.MaxValue]; Int32 bytes; TcpClient TcpClientSocket = new TcpClient(host,port); NetworkStream NetStrm = TcpClientSocket.GetStream(); szData = System.Text.Encoding.ASCII.GetBytes(cmd.ToCharArray()); NetStrm.Write(szData,0,szData.Length); while(true) { try { bytes = NetStrm.Read(RecvBytes, 0,RecvBytes.Length); clientSocket.Send(RecvBytes,bytes,SocketFlags.None); if (bytes<=0) break; } catch { UserInterface.reportMessage("Failed connect"); break; } } } [...]... any packets sent The program goes into an in nite loop at this point, receiving arrays of bytes from whomever happens also to be transmitting on that multicast IP address These byte arrays are then converted into strings and displayed on-screen To finish this code, add the required namespaces as follows: C# using using using using System.Threading; System.Net; System.Net.Sockets; System.Text; 11.4 Data... contain more than one source file and retain CRC and date information with each file to help maintain integrity The ZipOutputStream is appended to using ZipEntry objects Each entry contains the original file data, along with a CRC for that file and a date 11.5 Lossless compression 293 Note: Checksums (or CRCs) are similar to hash values, although they are used for integrity checks rather than security against... While Catch UserInterface.reportMessage("Failed connect") Exit While End Try End While End Sub As usual, some standard namespaces are added to the head of the code: C# using using using using using System.Net; System.Net.Sockets; System.Text; System.IO; System.Threading; VB.NET Imports Imports Imports Imports Imports System.Net System.Net.Sockets System.Text System.IO System.Threading To test the application,... Sub The receiving thread will remain in an in nite loop awaiting new data It is therefore run in a separate thread named recieverThread() In this case, the multicast functionality is implemented using the the UdpClient object Membership to the group is obtained by calling JoinMulticastGroup Again the TTL and port details must be specified Enter the following code to finish this application: C# public void... phase, rather than ending up with a dozen versions of your product and the server downtime caused by implementing updates The next chapter deals with network performance, including techniques such as compression and multicast Chapter 10 This page intentionally left blank 11 Optimizing Bandwidth Utilization 11.1 Introduction You can’t always expect your customer to have the same bandwidth as your office... travel anywhere in the world The message, which is in string format, is converted to a byte array The endpoint is set to the multicast address on the port specified The socket then connects to the endpoint, sends the byte array, and then disconnects To complete the program, add the required namespaces at the top of the code: C# using System.Text; using System.Net; using System.Net.Sockets; VB.NET Imports... described later This tweak reduces protocol overhead by eliminating part of the safety net and trimming some of the time involved in the turnaround of an ACK TcpWindowSize can also exist under \Parameters\Interface\ If the setting is added at this location, it overrides the global setting When the window size is less than 64 K, the Tcp1323Opts setting should be applied as detailed below: HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\... exponentially and end up clogging routers all over the Internet 11.3.2 Multicast routing Multicast UDP may be the first non-P2P protocol to be accessible programmatically, but there is nothing new in protocols that broadcast rather than going from A to B Routing protocols such as RIP and OSPF do not have set endpoints; rather, they percolate through networks in all directions at once In fact, it would... Figure 11.1 Multicast UDP client and server VB.NET Imports Imports Imports Imports System.Threading System.Net System.Net.Sockets System.Text To test this application, run both the sender and receiver from Visual Studio NET Set the group address on the sender to 224.5 .6. 7 and the port to 5000, type in a short message, and press send You will see the text appearing in the receiver application (Figure... someone could run off with $499,999 without affecting the books There are two ways of compressing data without losing integrity: entropy encoding and source encoding Entropy encoding is where the statistical similarity between bytes or byte sequences is recorded, rather than the bytes themselves Source encoding is where the rate of change between bytes or byte sequences is recorded and not the bytes themselves . unresponsive. Finally, the threading namespace is required: C# using System.Threading; VB .NET imports System.Threading To test the application, run it from Visual Studio .NET and wait for a minute. chapter deals with network performance, including techniques such as compression and multicast. This page intentionally left blank 275 11 Optimizing Bandwidth Utilization 11.1 Introduction . eliminating part of the safety net and trim- ming some of the time involved in the turnaround of an ACK. TcpWindowSize can also exist under ParametersInterface . If the setting is

Ngày đăng: 12/08/2014, 21:20

TỪ KHÓA LIÊN QUAN