Tải bản đầy đủ - 0 (trang)
10-9. Ping an IP Address

10-9. Ping an IP Address

Tải bản đầy đủ - 0trang

CHAPTER 10 ■ NETWORKING



The Send method will return a System.Net.NetworkInformation.PingReply object. The Status

property of the PingReply will contain a value from the System.Net.NetworkInformation.IPStatus

enumeration from which you can determine the result of the ping request. The most common values

will be Success and TimedOut. If the host name you pass to the Send method cannot be resolved, Send will

throw an exception, but you must look at the InnerException to determine the cause of the problem.

The Ping class also provides a SendAsync method that performs the ping request using a thread-pool

thread so that the calling thread does not block. When the ping is finished or fails because of a timeout,

the thread raises the PingCompleted event on the Ping object, which you can handle using a method that

matches the signature of the System.Net.NetworkInformation.PingCompletedEventHandler delegate.

However, the Ping object can handle only a single concurrent request; otherwise, it will throw a

System.InvalidOperationException.



■ Tip The Ping class derives from System.ComponentModel.Component, so you can add it to the Visual Studio

Form Designer Toolbox in order to allow you to easily set the properties or define the event handlers in a Windows

Forms–based application.



The Code

The following example pings the computers whose domain names or IP addresses are specified as

command-line arguments:

using System;

using System.Net.NetworkInformation;

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_09

{

public static void Main(string[] args)

{

// Create an instance of the Ping class.

using (Ping ping = new Ping())

{

Console.WriteLine("Pinging:");

foreach (string comp in args)

{

try

{

Console.Write("

{0}...", comp);

// Ping the specified computer with a timeout of 100 ms.

PingReply reply = ping.Send(comp, 100);



508



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



if (reply.Status == IPStatus.Success)

{

Console.WriteLine("Success - IP Address:{0} Time:{1}ms",

reply.Address, reply.RoundtripTime);

}

else

{

Console.WriteLine(reply.Status);

}

}

catch (Exception ex)

{

Console.WriteLine("Error ({0})",

ex.InnerException.Message);

}

}

}

// Wait to continue.

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Main method complete. Press Enter");

Console.ReadLine();

}

}

}



Usage

Running the example with the following command line:

recipe10-09 www.apress.com www.google.com localhost somejunk

will produce output similar to the following:

Pinging:

www.apress.com...TimedOut

www.google.com...Success - IP Address:216.239.59.104 Time:42ms

localhost...Success - IP Address:127.0.0.1 Time:0ms

somejunk...Error (No such host is known)



509



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



10-10. Communicate Using TCP

Problem

You need to send data between two computers on a network using a TCP/IP connection.



Solution

One computer (the server) must begin listening using the System.Net.Sockets.TcpListener class.

Another computer (the client) connects to it using the System.Net.Sockets.TcpClient class. Once a

connection is established, both computers can communicate using the System.Net.Sockets.

NetworkStream class.



How It Works

TCP is a reliable, connection-oriented protocol that allows two computers to communicate over a

network. It provides built-in flow control, sequencing, and error handling, which makes it reliable and

easy to program.

To create a TCP connection, one computer must act as the server and start listening on a specific

endpoint. (An endpoint is a combination of an IP address and a port number.) The other computer must

act as a client and send a connection request to the endpoint on which the first computer is listening.

Once the connection is established, the two computers can take turns exchanging messages. .NET

makes this process easy through its stream abstraction. Both computers simply write to and read from a

System.Net.Sockets.NetworkStream to transmit data.



■ Note Even though a TCP connection always requires a server and a client, an individual application could be

both. For example, in a peer-to-peer application, one thread is dedicated to listening for incoming requests (acting

as a server), and another thread is dedicated to initiating outgoing connections (acting as a client). In the examples

provided with this chapter, the client and server are provided as separate applications and are placed in separate

subdirectories.



Once a TCP connection is established, the two computers can send any type of data by writing it to

the NetworkStream. However, it’s a good idea to begin designing a networked application by defining the

application-level protocol that clients and servers will use to communicate. This protocol includes

constants that represent the allowable commands, ensuring that your application code doesn’t include

hard-coded communication strings.



510



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



The Code

In this example, the defined protocol is basic. You would add more constants depending on the type of

application. For example, in a file transfer application, you might include a client message for requesting

a file. The server might then respond with an acknowledgment and return file details such as the file size.

These constants should be compiled into a separate class library assembly, which must be referenced by

both the client and server. Here is the code for the shared protocol:

namespace Apress.VisualCSharpRecipes.Chapter10

{

public class Recipe10_10Shared

{

public const string AcknowledgeOK = "OK";

public const string AcknowledgeCancel = "Cancel";

public const string Disconnect = "Bye";

public const string RequestConnect = "Hello";

}

}

The following code is a template for a basic TCP server. It listens on a fixed port, accepts the first

incoming connection, and then waits for the client to request a disconnect. At this point, the server

could call the TcpListener.AcceptTcpClient method again to wait for the next client, but instead it

simply shuts down.

using

using

using

using



System;

System.IO;

System.Net;

System.Net.Sockets;



namespace Apress.VisualCSharpRecipes.Chapter10

{

public class Recipe10_10Server

{

public static void Main()

{

// Create a new listener on port 8000.

TcpListener listener =

new TcpListener(IPAddress.Parse("127.0.0.1"), 8000);

Console.WriteLine("About to initialize port.");

listener.Start();

Console.WriteLine("Listening for a connection...");

try

{

// Wait for a connection request, and return a TcpClient

// initialized for communication.

using (TcpClient client = listener.AcceptTcpClient())

{

Console.WriteLine("Connection accepted.");



511



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



// Retrieve the network stream.

NetworkStream stream = client.GetStream();

// Create a BinaryWriter for writing to the stream.

using (BinaryWriter w = new BinaryWriter(stream))

{

// Create a BinaryReader for reading from the stream.

using (BinaryReader r = new BinaryReader(stream))

{

if (r.ReadString() ==

Recipe10_10Shared.RequestConnect)

{

w.Write(Recipe10_10Shared.AcknowledgeOK);

Console.WriteLine("Connection completed.");

while (r.ReadString() !=

Recipe10_10Shared.Disconnect) { }

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Disconnect request received.");

}

else

{

Console.WriteLine("Can't complete connection.");

}

}

}

}

Console.WriteLine("Connection closed.");

}

catch (Exception ex)

{

Console.WriteLine(ex.ToString());

}

finally

{

// Close the underlying socket (stop listening for new requests).

listener.Stop();

Console.WriteLine("Listener stopped.");

}

// Wait to continue.

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Main method complete. Press Enter");

Console.ReadLine();

}

}

}



512



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



The following code is a template for a basic TCP client. It contacts the server at the specified IP

address and port. In this example, the loopback address (127.0.0.1) is used, which always points to the

local computer. Keep in mind that a TCP connection requires two ports: one at the server end and one at

the client end. However, only the server port to connect to needs to be specified. The outgoing client

port can be chosen dynamically at runtime from the available ports, which is what the TcpClient class

will do by default.

using

using

using

using



System;

System.IO;

System.Net;

System.Net.Sockets;



namespace Apress.VisualCSharpRecipes.Chapter10

{

public class Recipe10_10Client

{

public static void Main()

{

TcpClient client = new TcpClient();

try

{

Console.WriteLine("Attempting to connect to the server ",

"on port 8000.");

client.Connect(IPAddress.Parse("127.0.0.1"), 8000);

Console.WriteLine("Connection established.");

// Retrieve the network stream.

NetworkStream stream = client.GetStream();

// Create a BinaryWriter for writing to the stream.

using (BinaryWriter w = new BinaryWriter(stream))

{

// Create a BinaryReader for reading from the stream.

using (BinaryReader r = new BinaryReader(stream))

{

// Start a dialog.

w.Write(Recipe10_10Shared.RequestConnect);

if (r.ReadString() == Recipe10_10Shared.AcknowledgeOK)

{

Console.WriteLine("Connected.");

Console.WriteLine("Press Enter to disconnect.");

Console.ReadLine();

Console.WriteLine("Disconnecting...");

w.Write(Recipe10_10Shared.Disconnect);

}



513



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



else

{

Console.WriteLine("Connection not completed.");

}

}

}

}

catch (Exception err)

{

Console.WriteLine(err.ToString());

}

finally

{

// Close the connection socket.

client.Close();

Console.WriteLine("Port closed.");

}

// Wait to continue.

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Main method complete. Press Enter");

Console.ReadLine();

}

}

}



Usage

Here’s a sample connection transcript on the server side:

About to initialize port.

Listening for a connection...

Connection accepted.

Connection completed.

Disconnect request received.

Connection closed.

Listener stopped.

And here’s a sample connection transcript on the client side:

Attempting to connect to the server on port 8000.

Connection established.

Connected.

Press Enter to disconnect.

Disconnecting...

Port closed.



514



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



10-11. Create a Multithreaded TCP Server That Supports

Asynchronous Communications

Problem

You need to handle multiple network requests concurrently or perform a network data transfer as a

background task while your program continues with other processing.



Solution

Use the method AcceptTcpClient of the System.Net.Sockets.TcpListener class to accept connections.

Every time a new client connects, start a new thread to handle the connection. Alternatively, use the

TcpListener.BeginAcceptTcpClient to accept a new client connection on a thread-pool thread using the

asynchronous execution pattern (discussed in recipe 4-2).

To start a background task to handle the asynchronous sending of data, you can use the BeginWrite

method of the System.Net.Sockets.NetworkStream class and supply a callback method—each time the

callback is triggered, send more data.



How It Works

A single TCP endpoint (IP address and port) can serve multiple connections. In fact, the operating

system takes care of most of the work for you. All you need to do is create a worker object on the server

that will handle each connection on a separate thread. The TcpListener.AcceptTcpClient method

returns a TcpClient when a connection is established. This should be passed off to a threaded worker

object so that the worker can communicate with the remote client.

Alternatively, call the TcpListener.BeginAcceptTcpClient method to start an asynchronous

operation using a thread-pool thread that waits in the background for a client to connect.

BeginAcceptTcpClient follows the asynchronous execution pattern, allowing you to wait for the

operation to complete or specify a callback that the .NET runtime will call when a client connects.

(See recipe 4-2 for details on the options available.) Whichever mechanism you use, once

BeginAcceptTcpClient has completed, call EndAcceptTcpClient to obtain the newly created TcpClient

object.

To exchange network data asynchronously, you can use the NetworkStream class, which includes

basic support for asynchronous communication through the BeginRead and BeginWrite methods. Using

these methods, you can send or receive a block of data on one of the threads provided by the thread

pool, without blocking your code. When sending data asynchronously, you must send raw binary data

(an array of bytes). It’s up to you to choose the amount you want to send or receive at a time.

One advantage of this approach when sending files is that the entire content of the file does not

have to be held in memory at once. Instead, it is retrieved just before a new block is sent. Another

advantage is that the server can abort the transfer operation easily at any time.



515



www.it-ebooks.info



CHAPTER 10 ■ NETWORKING



The Code

The following example demonstrates various techniques for handling network connections and

communications asynchronously. The server (Recipe10-11Server) starts a thread-pool thread listening

for new connections using the TcpListener.BeginAcceptTcpClient method and specifying a callback

method to handle the new connections. Every time a client connects to the server, the callback method

obtains the new TcpClient object and passes it to a new threaded ClientHandler object to handle client

communications.

The ClientHandler object waits for the client to request data and then sends a large amount of data

(read from a file) to the client. This data is sent asynchronously, which means ClientHandler could

continue to perform other tasks. In this example, it simply monitors the network stream for messages

sent from the client. The client reads only a third of the data before sending a disconnect message to the

server, which terminates the remainder of the file transfer and drops the client connection.

Here is the code for the shared protocol:

namespace Apress.VisualCSharpRecipes.Chapter10

{

public class Recipe10_11Shared

{

public const string AcknowledgeOK = "OK";

public const string AcknowledgeCancel = "Cancel";

public const string Disconnect = "Bye";

public const string RequestConnect = "Hello";

public const string RequestData = "Data";

}

}

Here is the server code:

using

using

using

using

using



System;

System.IO;

System.Net;

System.Threading;

System.Net.Sockets;



namespace Apress.VisualCSharpRecipes.Chapter10

{

public class Recipe10_11Server

{

// A flag used to indicate whether the server is shutting down.

private static bool terminate;

public static bool Terminate { get { return terminate; } }

// A variable to track the identity of each client connection.

private static int ClientNumber = 0;

// A single TcpListener will accept all incoming client connections.

private static TcpListener listener;

public static void Main()

{



516



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

10-9. Ping an IP Address

Tải bản đầy đủ ngay(0 tr)

×