当前位置:  互联网>综合
本页文章导读:
    ▪在HTML中使用WCF RESTful上传文件      说明 在HTML中上传文件时会为文件内容加入一头一尾,如下所示: -----------------------8cc0b8cfcfd5ed2 Content-Disposition: form-data; name="file"; filename="item3.xml" Content-Type: application/octet-stream .........
    ▪skb_buf结构分析              转载请注明出处:http://blog.csdn.net/qq405180763/article/details/8797236          实际上skb_buf结构只是一块已经申请好的套接字缓冲区的指针和属性数据.........
    ▪微博URL(短超链接)的生成原理       新浪、腾讯、搜狐等微博网站都加入了短超链接的功能。之所以要是使用短链接,主要是因为微博只允许发140 字,如果链接地址太长的话,那么发送的字数将大大减少。短链接的主要职.........

[1]在HTML中使用WCF RESTful上传文件
    来源: 互联网  发布时间: 2013-10-21
说明

在HTML中上传文件时会为文件内容加入一头一尾,如下所示:

-----------------------8cc0b8cfcfd5ed2
Content-Disposition: form-data; name="file"; filename="item3.xml"
Content-Type: application/octet-stream

这里是真正的文件内容
-----------------------8cc0b8cfcfd5ed2--

因此服务端接收后要手动对其作解析。



代码 网页端

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
    <meta http-equiv="pragma" content="no-cache" />
    <title>测试页</title>
</head>

<body>
    文件上传页
        <form action="http://localhost:4513/IVisitorRestService/Upload/utf-8" method="POST" enctype="multipart/form-data">
            <input type="file" />
            <input type="submit" />
        </form>
</body>
</html>



服务端 契约

/// <summary>
/// 使用HTML上传文件
/// </summary>
/// <param name="file">文件流</param>
/// <param name="encodingName">HTML的文字编码名</param>
[Custom(AllowAnonymousForOperation = true)]
[WebInvoke(Method = "POST", UriTemplate = "Upload/{encodingName}")]
void Upload(Stream file, string encodingName);


实现

public void Upload(Stream file, string encodingName)
{
    using (var ms = new MemoryStream())
    {
        file.CopyTo(ms);
        ms.Position = 0;

        var encoding = Encoding.GetEncoding(encodingName);
        var reader = new StreamReader(ms, encoding);
        var headerLength = 0L;

        //读取第一行
        var firstLine = reader.ReadLine();
        //计算偏移(字符串长度+回车换行2个字符)
        headerLength += encoding.GetBytes(firstLine).LongLength + 2;

        //读取第二行
        var secondLine = reader.ReadLine();
        //计算偏移(字符串长度+回车换行2个字符)
        headerLength += encoding.GetBytes(secondLine).LongLength + 2;
        //解析文件名
        var fileName = new System.Text.RegularExpressions.Regex("filename=\"(?<fn>.*)\"").Match(secondLine).Groups["fn"].Value;

        //一直读到空行为止
        while (true)
        {
            //读取一行
            var line = reader.ReadLine();
            //若到头,则直接返回
            if (line == null)
                break;
            //若未到头,则计算偏移(字符串长度+回车换行2个字符)
            headerLength += encoding.GetBytes(line).LongLength + 2;
            if (line == "")
                break;
        }

        //设置偏移,以开始读取文件内容
        ms.Position = headerLength;
        ////减去末尾的字符串:“\r\n--\r\n”
        ms.SetLength(ms.Length - encoding.GetBytes(firstLine).LongLength - 3 * 2);

        using (var fileToupload = new FileStream("D:\\FileUpload\\" + fileName, FileMode.Create))
        {
            ms.CopyTo(fileToupload);
            fileToupload.Close();
            fileToupload.Dispose();
        }
    }
}


作者:iaki2008 发表于2013-4-12 15:15:46 原文链接
阅读:63 评论:0 查看评论

    
[2]skb_buf结构分析
    来源: 互联网  发布时间: 2013-10-21

        转载请注明出处:http://blog.csdn.net/qq405180763/article/details/8797236 

        实际上skb_buf结构只是一块已经申请好的套接字缓冲区的指针和属性数据的描述集合,netdev_alloc_skb函数申请到一块套接字缓冲区后,返回记录这块缓冲区信息的skb_buf结构,在各个网络层传输的只是skb_buf结构,换句话说,仅仅是该套接字缓冲区的指针而已,各个网络层根据传来的指针,对指针进行操作,往已经申请好的固定套接字缓冲区里读写数据。

        sk_buff结构的成员skb->head指向一个已分配的空间的头部,即申请到的整个缓冲区的头,skb->end指向该空间的尾部,这两个成员指针从空间创建之后,就不能被修改。skb->data指向分配空间中数据的头部,skb->tail指向数据的尾部,这两个值随着网络数据在各层之间的传递、修改,会被不断改动,而skb->head和skb->date之间,则是相应层对应的协议头。四个指针间存在如下关系:
                                                                             

        sk_buff结构被不同的网络层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量(一般是数据指针)在结构从一层向另一层传递时改变。L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部。添加头部比在不同层之间拷贝数据的效率更高。由于在缓冲区的头部(skb->head和skb->date之间)添加数据意味着要修改指向缓冲区的指针,这是个复杂的操作,所以内核提供了一个函数skb_reserve将数据(date)部分往后移。协议栈中的每一层在往下一层传递缓冲区前,第一件事就是调用skb_reserve在缓冲区的头部给协议头预留一定的空间,再用skb_push函数将协议头查到skb->data指针之前。

        skb_reserve同样被设备驱动使用来对齐接收到包的包头。如果缓冲区向上层协议传递,旧的协议层的头部信息就没什么用了。例如,L2的头部只有在网络驱动处理L2的协议时有用,L3是不会关心它的信息的。但是,内核并没有把L2的头部从缓冲区中删除,而是用sk_buff结构中对应的头指针指向这个头,再把有效荷载的指针指向L3的头部,这样做,可以节省CPU时间。当接收一个包时,处理n层协议头的函数从n-1层收到一个缓冲区,因为在n-1层处理的最后,skb->data是指向n-1层的数据开始指针,所以到了n层后skb->data就是指向n层协议的头。处理n层协议的函数把本层的指针(例如,L3对应的是skb- >nh指针)初始化为skb->data,取出本层的协议头指针,在处理n层协议的函数结束时,在把包传递给n+1层的处理函数前,它会把skb->data指针指向n层协议头的末尾,这正好是n+1层协议的协议头(参见下图)。

                      

           skb_buf在各个网络层传输过程及skb_buf操作函数。

        在网络数据发送过程中,由netdev_alloc_skb申请得到套接字缓冲区后,skb_reserve将整个数据块往后移动MAX_TCP_HEADER个字节,预留出skb中协议头的最大长度,确保在套接字从上层不断往下层传递的过程中,有足够的协议头空间。在数据每传到一个网络层的时候,通过skb_push函数将该层的协议头插到skb->data前面,一直到链路层将所有层的协议头加入到套接字协议头部分(从skb->head到skb->data之间),skb_push函数几乎就是用来在skb->data前面插入协议头的。最后由驱动程序把数据发给网卡,释放掉套接字缓存,网卡负责把数据发到网络上。

        在网络数据接收过程中,网卡收到数据触发中断,驱动程序响应中断接收网卡缓存中数据,因为网卡中以太网帧头的长度为14个字节,而紧接着的IP协议头需要在16字节对齐的边界上,所以在申请到套接字缓存后,用skb_reserve函数先预留出2字节的空间,确保IP协议头的16字节对齐。刚申请到的套接字缓存,其sbk_buf的skb->data和skb->tail是同一个值,是没有数据的,用skb_put函数将skb->tail往后拉数据包长度个字节空间,然后把网络数据从网卡中拷贝到套接字缓存里,skb_put函数就是在skb->tail和skb->end之间加数据。接着将数据往上层发送,在每一层中用skb_pull函数或者移动skb->data指针的方式,将各个层对应的协议头从数据中剥离开来,一直到最上面的应用层,剩下真正的从其他机器发过来的有用数据。

作者:qq405180763 发表于2013-4-13 17:13:45 原文链接
阅读:19 评论:0 查看评论

    
[3]微博URL(短超链接)的生成原理
    来源: 互联网  发布时间: 2013-10-21

新浪、腾讯、搜狐等微博网站都加入了短超链接的功能。之所以要是使用短链接,主要是因为微博只允许发140 字,如果链接地址太长的话,那么发送的字数将大大减少。短链接的主要职责就是把原始链接很长的地址压缩成只有6 个字母的短链接地址,当我们点击这6 个字母的链接后,我们又可以跳转到原始链接地址。

开始以为短链接是按照某种算法把原始链接压缩为短链接,再根据算法从短链接反算成原始链接的。后来尝试了下压缩算法(gzip 压缩算法),发现对于url 这种字符串越是压缩,长度就越长。通过对压缩算法的一些了解,发现靠压缩算法来实现这个功能不太靠谱。

后来在网上找到一个生成算法,该算法主要使用MD5 算法对原始链接进行加密(这里使用的MD5 加密后的字符串长度为32 位),然后对加密后的字符串进行处理以得到短链接的地址。原始的算法是C# 版本的,这里我把该算法修改成Java 版本的. 算法的具体代码如下,代码中有注释:

一、  代码

package com.csdn.shorturl;

public class ShortUrlGenerator {

 

    /**

      * @param args

      */

    public static void main(String[] args) {

       // 长连接: http://tech.sina.com.cn/i/2011-03-23/11285321288.shtml

       // 新浪解析后的短链接为: http://t.cn/h1jGSC

       String sLongUrl = "http://tech.sina.com.cn/i/2011-03-23/11285321288.shtml" ; // 3BD768E58042156E54626860E241E999

       String[] aResult = shortUrl (sLongUrl);

       // 打印出结果

       for ( int i = 0; i < aResult. length ; i++) {

           System. out .println( "[" + i + "]:::" + aResult[i]);

       }

    }

 

    public static String[] shortUrl(/blog_article/String url/index.html) {

       // 可以自定义生成 MD5 加密字符传前的混合 KEY

       String key = "wuguowei" ;

       // 要使用生成 URL 的字符

       String[] chars = new String[] { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" ,

              "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" ,

              "u" , "v" , "w" , "x" , "y" , "z" , "0" , "1" , "2" , "3" , "4" , "5" ,

              "6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" ,

              "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T" ,

              "U" , "V" , "W" , "X" , "Y" , "Z"

 

       };

       // 对传入网址进行 MD5 加密

       String sMD5EncryptResult = ( new CMyEncrypt()).getMD5OfStr(key + url);

       String hex = sMD5EncryptResult;

 

       String[] resUrl = new String[4];

       for ( int i = 0; i < 4; i++) {

 

           // 把加密字符按照 8 位一组 16 进制与 0x3FFFFFFF 进行位与运算

           String sTempSubString = hex.substring(i * 8, i * 8 + 8);

 

           // 这里需要使用 long 型来转换,因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用 long ,则会越界

           long lHexLong = 0x3FFFFFFF & Long.parseLong (sTempSubString, 16);

           String outChars = "" ;

           for ( int j = 0; j < 6; j++) {

              // 把得到的值与 0x0000003D 进行位与运算,取得字符数组 chars 索引

              long index = 0x0000003D & lHexLong;

              // 把取得的字符相加

              outChars += chars[( int ) index];

              // 每次循环按位右移 5 位

              lHexLong = lHexLong >> 5;

           }

           // 把字符串存入对应索引的输出数组

           resUrl[i] = outChars;

       }


    
最新技术文章:
▪用户及权限基础 2---- Linux权限    ▪用户及权限基础 3---- Linux扩展权限    ▪git 简明教程(1) --创建及提交
▪背包 代码    ▪json对象的封装与解析    ▪01背包,完全背包,多重背包 ,模板代码
▪apache安装详解    ▪HDU 4668 Finding string (解析字符串 + KMP)    ▪《TCP-IP详解 卷1:协议》学习笔记(二)
技术文章 iis7站长之家
▪Linux Shell脚本编程--nc命令使用详解    ▪solr对跨服务器表联合查询的配置    ▪递归和非递归实现链表反转
▪Linux磁盘及文件系统管理 1---- 磁盘基本概念    ▪Cholesky Decomposition    ▪HTTP协议学习
▪用C语言写CGI入门教程    ▪用hdfs存储海量的视频数据的设计思路    ▪java多线程下载的实现示例
▪【原创】eAccelerator 一个锁bug问题跟踪    ▪hadoop学习之ZooKeeper    ▪使用cuzysdk web API 实现购物导航类网站
▪二维数组中的最长递减子序列    ▪内嵌W5100的网络模块WIZ812MJ--数据手册    ▪xss 跨站脚本攻击
▪RobotFramework+Selenium2环境搭建与入门实例    ▪什么是API    ▪用PersonalRank实现基于图的推荐算法
▪Logtype    ▪关于端口号你知道多少!    ▪Linux基本操作 1-----命令行BASH的基本操作
▪CI8.7--硬币组合问题    ▪Ruby on Rails 学习(五)    ▪如何使用W5300实现ADSL连接(二)
▪不允许启动新事务,因为有其他线程正在该会...    ▪getting start with storm 翻译 第六章 part-3    ▪递归求排列和组合(无重复和有重复)
▪工具类之二:RegexpUtils    ▪Coding Interview 8.2    ▪Coding Interview 8.5
▪素因子分解 Prime factorization    ▪C# DllImport的用法    ▪图的相关算法
▪Softmax算法:逻辑回归的扩展    ▪最小生成树---Kruskal算法---挑战程序设计竞赛...    ▪J2EE struts2 登录验证
▪任意两点间的最短路径---floyd_warshall算法    ▪Sqoop实现关系型数据库到hive的数据传输    ▪FFMPEG采集摄像头数据并切片为iPhone的HTTP Stream...
▪Ubuntu 13.04 – Install Jetty 9    ▪TCP/IP笔记之多播与广播    ▪keytool+tomcat配置HTTPS双向证书认证
▪安装phantomjs    ▪Page Redirect Speed Test    ▪windows media player 中播放pls的方法
▪sre_constants.error: unbalanced parenthesis    ▪http headers    ▪Google MapReduce中文版
▪The TCP three-way handshake (connect)/four wave (closed)    ▪网站反爬虫    ▪Log4j实现对Java日志的配置全攻略
▪Bit Map解析    ▪Notepad 快捷键 大全    ▪Eclipse 快捷键技巧 + 重构
▪win7 打开防火墙端口    ▪Linux Shell脚本入门--awk命令详解    ▪Linux Shell脚本入门--Uniq命令
▪Linux(Android NDK)如何避免僵死进程    ▪http Content-Type一览表    ▪Redis实战之征服 Redis + Jedis + Spring (二)
▪Tomcat7.0.40 基于DataSourceRealm的和JDBCRealm的资源...    ▪利用SQOOP将ORACLE到HDFS    ▪django输出 hello world
▪python re    ▪unity3D与网页的交互    ▪内存共享基本演示
▪python join    ▪不再为无限级树结构烦恼,且看此篇    ▪python实现变参
▪打开文件数限制功能不断地制造问题    ▪Arduino Due, Maple and Teensy3.0 的 W5200性能测试    ▪Selenium实例----12306网站测试
▪基于协同过滤的推荐引擎    ▪C4.5决策树    ▪C#HTTP代理的实现之注册表实现
▪nosql和关系型数据库比较?    ▪如何快速比较这两个字符串是否相等?    ▪hdoj 1863 畅通工程 最小生成树---prime算法
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3