首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 图形图象-> FLASH教程
使用c#查询路由接口,同时小议一些.net 2.0的诡异api_c#应用
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

有时候我们希望知道程序正在使用那个IP地址连接到远程的服务器(类似pathping命令返回的第一个结果,P2P应用中尤其多见),文末的代码可以完成这个任务

写完这段代码之后,我对.net API的设计有些不满了。

首先就是Socket类的IOControl方法,该方法脱胎于Winsock2 API的WSAIoctl函数。对于基于C语言的Winsock2 API,设计出WSAIoctl显得还合情合理,虽然冗长的参数列表很是吓人,但是对于面向对象的C#,居然还需要使用byte[]这些弱类型的数据结构来做参数,实在是有些匪夷所思了,我觉得Socket类应该对IOControl进行充分的包装,以便没有Win32 API经验的用户更好的使用。


接着是IPEndPoint的序列化形式SocketAddress类,这个类明显的与sockaddr structure一样,不同的是,它比sockaddr structure更加难以使用。它提供了一个象数组一样的索引器,允许用户以[]运算符获取其中的byte元素,但是却不提供方法简便的将其中的内容复制到一个byte[]中供Socket.IOControl调用,竟然需要客户自己使用循环来调用,实在傻的可以。


最后是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];

        }

 

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

 

        sock.IOControl(IOControlCode.RoutingInterfaceQuery,

                                   addrBytes,

                                   outBytes);

 

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

        {

            sa[i] = outBytes[i];

        }

 

 

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

 

        return (IPEndPoint)ep;

    }

 

    /// <summary>

    /// 根据SocketAddress创建IPEndPoint

    /// </summary>

    /// <remarks>该函数从IPEndPoint的Create方法反编译出来</remarks>

    /// <param name="socketAddress"></param>

    /// <returns></returns>

    public static IPEndPoint CreateIPEndPoint(SocketAddress socketAddress)

    {

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

        //{

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

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

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

        //            "socketAddress");

        //}

 

        if (socketAddress.Size < 8)

        {

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

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

            //        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[2] << 8) & 0xff00) | socketAddress[3];

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

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

                + (socketAddress[0x19] << 8)) +

                        socketAddress[0x18];

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

        }

 

        int num4 = ((socketAddress[2] << 8) & 0xff00) | socketAddress[3];

 

        long num5 = ((((socketAddress[4] & 0xff)

            | ((socketAddress[5] << 8) & 0xff00))

            | ((socketAddress[6] << 0x10) & 0xff0000))

            | (socketAddress[7] << 0x18)) & ((long)0xffffffff);

 

        return new IPEndPoint(num5, num4);

    }

 

 

    static void Main(string[] args)

    {

        try

        {

            Socket s = new Socket(AddressFamily.InterNetwork,

                                  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);

            Console.WriteLine(ep);

        }

        catch (SocketException e)

        {

            Console.WriteLine(e);

            Console.WriteLine(e.ErrorCode);

        }

    }

}


程序的核心是QueryRoutingInterface方法,代码相当的简单,我就不多做解释了。
http://www.cnblogs.com/ncindy/archive/2007/01/02/610148.html


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·adodb.stream对象的方法/属性-ASP教程,数据库相关
·DataGrid - 导出Excel文件-.NET教程,数据库应用
·有滚动条、固定Header的ASP.Net DataGrid实现-ASP教程,数据库相关
·解决Windows 程序界面闪烁问题的一些经验-.NET教程,Windows开发
·C#数据访问类-.NET教程,C#语言
·jsp生成html--replace-JSP教程,Jsp/Servlet
·查询两个表中字段个数不同,名称不同的SQL语句-ASP教程,数据库相关
·【C#】输入汉字字符串索引拼音的首字母-.NET教程,C#语言
·使用SQLServer2005-.NET教程,Web Service开发
·Java语言中字符的处理-JSP教程,Java技巧及代码
最新文章
·flash中作毛笔写字动画效果_flash教程
·用dreamweaver制作网页时关于文字自动换行的小技巧_dreamweaver教程
·seo中十大影响链接权重的因素浅析_seo网站优化
·在windows vista系统下扩大“发送到”的范围_windows vista
·众多网站引入嵌入式广告 网络广告面临拐点_站长访谈
·王怀南:遍地都是黄金 宝宝树创新模式_站长访谈
·幻想着靠蓝海大赚是不可能的_站长心得
·谈谈做站与站长的站德问题_站长心得
·photoshop打造非主流效果—颓废诡异效果_photoshop教程
·google pagerank 技术解密 1_google推广
相关主题
西部数码虚拟主机

友情链接
CNNIC 西部数码
万网 自助建站
虚拟主机 asp空间
域名注册 域名
域名申请 主页空间
论坛空间 网站空间
国际域名 虚拟空间
空间租用 DDOS防火墙
成都主机托管 四川主机托管
主机租用 服务器租用
网站目录 自助建站
虚拟主机 网址大全
软件下载
自助链接
虚拟主机资讯 特价虚拟主机
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
发表评论 打印  刷新     关闭