程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 使用C#查詢路由接口,同時小議一些.net 2.0的詭異API

使用C#查詢路由接口,同時小議一些.net 2.0的詭異API

編輯:關於C語言

有時候我們希望知道程序正在使用那個IP地址連接到遠程的服務器(類似pathping命令返回的第一個結果,P2P應用中尤其多見),文末的代碼可以完成這個任務

寫完這段代碼之後,我對.Net(.Net培訓 ) API的設計有些不滿了。

首先就是Socket類的IOControl方法,該方法脫胎於Winsock2 API的WSAIoctl函數。對於基於C語言的Winsock2 API,設計出WSAIoctl顯得還合情合理,雖然冗長的參數列表很是嚇人,但是對於面向對象的C#(C#培訓 ),居然還需要使用byte[]這些弱類型的數據結構來做參數,實在是有些匪夷所思了,我覺得Socket類應該對IOControl進行充分的包裝,以便沒有Win32 API經驗的用戶更好的使用。

接著是IPEndPoint的序列化形式SocketAddress類,這個類明顯的與sockaddr structure一樣,不同的是,它比sockaddr structure更加難以使用。它提供了一個象數組一樣的索引器,允許用戶以[]運算符獲取其中的byte元素,但是卻不提供方法簡便的將其中的內容復制到一個byte[]中供Socket.IOControl調用,竟然需要客戶自己使用循環來調用,實在傻的可以。

http://www.mscto.com

最後是IPEndPoint,它居然需要實例化之後才能調用Create成員函數把一個SocketAddress實例反序列化成一個IPEndPoint對象,我暈,為啥不是靜態的呢?看了這個Create方法的代碼之後,我發現完全沒有必要將其做成成員函數(為了證明靜態方法的可行,我在文中創建了一個CreateIPEndPoint靜態方法,並用它替換了IPEndPoint.Create成員方法),不知道為了使這個方法看起來更像是成員方法還是其他什麼原因,SocketAddress的AddressFamily居然必須和IPEndPoint實例的AddressFamily一致,否則就拋出異常,狂暈,人家反序列化還得看你一個不知所謂的對象的臉色,真是慘。

以上是我的觀點,歡迎大家一起議議。

using System;

using System.Net.Sockets;

using System.Net;

class Program

{

static IPEndPoint QueryRoutingInterface(Socket sock,

IPEndPoint remoteEP)

{

SocketAddress sa = remoteEP.Serialize();

byte[] addrBytes = new byte[sa.Size];

for (int i = 0; i < sa.Size; i )

{

addrBytes[i] = sa[i]; http://www.mscto.com

}

http://www.mscto.com

byte[] outBytes = new byte[addrBytes.Length];

http://www.mscto.com

sock.IOControl(IOControlCode.RoutingInterfaceQuery,

addrBytes, http://www.mscto.com

outBytes);

for (int i = 0; i < sa.Size; i )

{

sa[i] = outBytes[i];

}

EndPoint ep = CreateIPEndPoint(sa);//remoteEP.Create(sa);

return (IPEndPoint)ep;

}

///

/// 根據SocketAddress創建IPEndPoint

///

http://www.mscto.com

/// 該函數從IPEndPoint的Create方法反編譯出來

http://www.mscto.com

///

///

public static IPEndPoint CreateIPEndPoint(SocketAddress socketAddress)

{

//if (socketAddress.Family != this.AddressFamily)

//{

// throw new ArgumentException(SR.GetString(.Net(.Net培訓 )_InvalidAddressFamily",

// new object[] { socketAddress.Family.ToString(),

// base.GetType().FullName, this.AddressFamily.ToString() }),

// "socketAddress"); http://www.mscto.com

//}

http://www.mscto.com

if (socketAddress.Size < 8)

{

//throw new ArgumentException(SR.GetString("net_InvalidSocketAddressSize",

// new object[] { socketAddress.GetType().FullName,

http://www.mscto.com

// base.GetType().FullName }),

// "socketAddress");

throw new ArgumentException();

}

//if (this.AddressFamily == AddressFamily.InterNetworkV6)

if (socketAddress.Family == AddressFamily.InterNetworkV6)

{

byte[] buffer1 = new byte[0x10];

for (int num1 = 0; num1 < buffer1.Length; num1 )

{

buffer1[num1] = socketAddress[num1 8];

}

int num2 = ((socketAddress << 8) & 0xff00) | socketAddress; http://www.mscto.com

long num3 = (((socketAddress[0x1b] << 0x18)

(socketAddress[0x1a] << 0x10))

(socketAddress[0x19] << 8))

socketAddress[0x18];

return new IPEndPoint(new IPAddress(buffer1, num3), num2);

}

http://www.mscto.com

int num4 = ((socketAddress << 8) & 0xff00) | socketAddress;

http://www.mscto.com

long num5 = ((((socketAddress & 0xff)

| ((socketAddress << 8) & 0xff00))

| ((socketAddress << 0x10) & 0xff0000))

| (socketAddress << 0x18)) & ((long)0xffffffff);

return new IPEndPoint(num5, num4);

}

static void Main(string[] args)

{

try

{

Socket s = new Socket(AddressFamily.InterNetwork, http://www.mscto.com

SocketType.Dgram,

ProtocolType.Udp);

s.Bind(new IPEndPoint(IPAddress.Any, 10001));

IPEndPoint remoteEP = new IPEndPoint(

Dns.GetHostAddresses("www.google.com")[0],

1000);

IPEndPoint ep = QueryRoutingInterface(s, remoteEP);

Console.WriteLine(remoteEP);

http://www.mscto.com

Console.WriteLine(ep);

}

catch (SocketException e)

{

Console.WriteLine(e);

Console.WriteLine(e.ErrorCode);

}

}

}

程序的核心是QueryRoutingInterface方法,代碼相當的簡單,我就不多做解釋了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved