In. NET, the implementation of the LAN Service is scanned. net LAN

Source: Internet
Author: User

In. NET, the implementation of the LAN Service is scanned. net LAN

In a recent project, you need to meet the following requirements:In the client program, scan all the machines in the network segment where the current machine is located to see If a service is started, and list all the machines that have started the service for the user to choose which service to connect.Note: The Service mentioned here is actually a program or service (such as a WCF Service) that listens to TCP-based requests on a fixed port ).

To implement this function, the core point is to initiate a TCP connection request to each IP address after obtaining the IP addresses of all machines in the same network segment of the current machine. If the request times out or other exceptions occur, if the connection is normal, the service is normal.

After implementation of basic functions and subsequent refactoring, we have the following code: an interface and a specific implementation class. It should be noted that in the following code, the interface is mentioned first, and then the specific class. during the development process, the class is created first, and then the interface is extracted. There are two reasons for extracting interfaces: one is to support IoC control inversion, and the other is to create new classes based on this interface to meet new requirements in the future.

I. Interface Definition

First, let's look at the interface:

/// <Summary> /// scan service /// </summary> public interface IServerScanner {/// <summary> /// scan completed /// </summary> event EventHandler <List <ConnectionResult> OnScanComplete; /// <summary> /// report the Scan progress /// </summary> event EventHandler <ScanProgressEventArgs> OnScanProgressChanged; /// <summary> /// scan port /// </summary> int ScanPort {get; set ;} /// <summary> /// Timeout duration of a single connection /// </summary> TimeSpan Timeout {get; set ;} /// <summary> /// returns whether the specified IP address and port can be connected. /// </summary> /// <param name = "ipAddress"> </param> /// <param name = "port"> </param> /// <returns> </returns> bool IsConnected (IPAddress ipAddress, int port ); /// <summary> /// returns whether the specified IP address and port can be connected. /// </summary> /// <param name = "ip"> </param> /// <param name = "port"> </param> /// <returns> </returns> bool IsConnected (string ip, int port); // <summary> // start scanning /// </summary> void StartScan ();}

The Timeout attribute controls the Timeout duration of each connection request.

II. Specific implementation

Let's take a look at the specific implementation classes:

/// <Summary> /// scan result /// </summary> public class ConnectionResult {// <summary> /// IPAddress /// </summary> public IPAddress Address {get; set ;}//< summary> /// whether the connection is available /// </summary> public bool CanConnected {get; set ;}} /// <summary> /// scan completed event parameters /// </summary> public class ScanCompleteEventArgs {// <summary> /// result set /// </ summary> public List <ConnectionResult> Reslut {get; set; }}/// <Summary> /// Scan progress event parameters /// </summary> public class ScanProgressEventArgs {// <summary> // progress percentage /// </summary> public int Percent {get; set ;}//< summary> /// scan the services in the LAN /// </summary> public class server=: IServerScanner {// <summary> // number of IP addresses in the same network segment /// </summary> private const int SegmentIpMaxCount = 255; private DateTimeOffset _ endTime; private object _ locker = new Object (); private SynchronizationContext _ originalContext = SynchronizationContext. current; private List <ConnectionResult> _ resultList = new List <ConnectionResult> (); private DateTimeOffset _ startTime; /// <summary> /// record the number of calls/completed delegates /// </summary> private int _ totalCount = 0; public serverdetail () {Timeout = TimeSpan. fromSeconds (2) ;}/// <summary> /// this event is triggered when the scan is complete /// </summary> public event Ev EntHandler <List <ConnectionResult> OnScanComplete; // <summary> // when the Scan progress changes, trigger this event // </summary> public event EventHandler <ScanProgressEventArgs> OnScanProgressChanged; /// <summary> /// scan port /// </summary> public int ScanPort {get; set ;} /// <summary> /// Timeout duration of a single request. The default value is 2 seconds. /// </summary> public TimeSpan Timeout {get; set ;} /// <summary> /// use TcpClient to test whether the specified IP address and Port can be connected. /// </summary> /// <Param name = "ipAddress"> </param> /// <param name = "port"> </param> /// <returns> </returns> public bool IsConnected (IPAddress ipAddress, int port) {var result = TestConnection (ipAddress, port); return result. canConnected ;} /// <summary> /// use TcpClient to test whether the specified IP address and Port can be connected. /// </summary> /// <param name = "ip"> </ param> /// <param name = "port"> </param> /// <returns> </returns> public bool IsConnec Ted (string ip, int port) {IPAddress ipAddress; if (IPAddress. tryParse (ip, out ipAddress) {return IsConnected (ipAddress, port);} else {throw new ArgumentException ("Incorrect IP address format ");}} /// <summary> /// start to scan the current network segment /// </summary> public void StartScan () {if (ScanPort = 0) {throw new InvalidOperationException ("Scan port ScanPort must be specified");} // clear possible data _ resultList. clear (); _ totalCount = 0; _ startTime = DateTimeOffset. now; // obtain the IP var ipList = GetAllRemoteIPList () in this section; // generate the delegate List <Func <IPAddress, int, connectionResult> funcs = new List <Func <IPAddress, int, ConnectionResult> (); for (int I = 0; I <SegmentIpMaxCount; I ++) {var tmpF = new Func <IPAddress, int, ConnectionResult> (TestConnection); funcs. add (tmpF) ;}// asynchronously call each delegate for (int I = 0; I <SegmentIpMaxCount; I ++) {funcs [I]. beginInvoke (ip List [I], ScanPort, OnComplete, funcs [I]); _ totalCount + = 1 ;}} /// <summary> /// obtain all IP addresses in this segment /// </summary> /// <returns> </returns> private List <IPAddress> GetAllRemoteIPList () {var localName = Dns. getHostName (); var localIPEntry = Dns. getHostEntry (localName); List <IPAddress> ipList = new List <IPAddress> (); IPAddress localInterIP = localIPEntry. addressList. firstOrDefault (m => m. addressFamily = AddressFamily. interNetwork); if (localInterIP = null) {throw new InvalidOperationException ("the current computer does not have an intranet IP Address");} var localInterIPBytes = localInterIP. getAddressBytes (); for (int I = 1; I <= SegmentIpMaxCount; I ++) {// replace localInterIPBytes [3] = (byte) I; ipList. add (new IPAddress (localInterIPBytes);} return ipList;} private void OnComplete (IAsyncResult ar) {var state = ar. asyncState as Func <IPAddress, int, ConnectionResult>; var result = state. endInvoke (ar); lock (_ locker) {// Add to result _ resultList. add (result); // report progress _ totalCount-= 1; var percent = (SegmentIpMaxCount-_ totalCount) * 100/SegmentIpMaxCount; if (SynchronizationContext. current ==_ originalContext) {OnScanProgressChanged ?. Invoke (this, new ScanProgressEventArgs {Percent = percent});} else {_ originalContext. Post (conState => {OnScanProgressChanged ?. Invoke (this, new ScanProgressEventArgs {Percent = percent}) ;}, null) ;}if (_ totalCount = 0) {// result if (SynchronizationContext through the event throw. current ==_ originalContext) {OnScanComplete ?. Invoke (this, _ resultList);} else {_ originalContext. Post (conState => {OnScanComplete ?. Invoke (this, _ resultList) ;}, null) ;}// Debug the computing duration. writeLine ("Compete"); _ endTime = DateTimeOffset. now; Debug. writeLine ($ "Duration: {_ endTime-_ startTime }");}}} /// <summary> /// test whether the connection can be established. /// </summary> /// <param name = "address"> </param> /// <param name = "port"> </param> // <returns> </returns> private ConnectionResult TestConnection (IPAddress address, int port) {TcpClient c = new TcpClient (); ConnectionResult result = new ConnectionResult (); result. address = address; using (TcpClient tcp = new TcpClient () {IAsyncResult ar = tcp. beginConnect (address, port, null, null); WaitHandle wh = ar. asyncWaitHandle; try {if (! Ar. asyncWaitHandle. waitOne (Timeout, false) {tcp. close ();} else {tcp. endConnect (ar); result. canConnected = true;} catch {} finally {wh. close () ;}} return result ;}}
Serverstores

 

The comments in the above Code are basically more detailed. Here are a few simple points:

Iii. How to Use

Finally, let's take a look at how to use it, which is very simple:

Private void View_Loaded () {// Add the following code to the Load event on the page: servermetadata. onScanComplete + = ServerScanner_OnScanComplete; servercomplete. onScanProgressChanged + = ServerScanner_OnScanProgressChanged; // scan the port number serverslave. scanPort = 7890;} private void StartScan () {// start scanning serverdetail. startScan ();} private void ServerScanner_OnScanComplete (object sender, List <ConnectionResult> e ){...} private void ServerScanner_OnScanProgressChanged (object sender, ScanProgressEventArgs e ){...}

If you have better suggestions or comments, please leave a message to communicate with each other.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.