[转]【Java TCP/IP Socket】深入剖析socket——数据传输的底层实现

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

    底层数据结构

    如果不理解套接字的具体实现所关联的数据结构和底层协议的工作细节,就很难抓住网络编程的精妙之处,对于TCP套接字来说,更是如此。套接字所关联的底层的数据结构集包含了特定Socket实例所关联的信息。比附,套接字结构除其他信息外还包含:

    1、该套接字所关联的本地和远程互联网地址和端口号。

    2、一个FIFO(First Im First Out)队列,用于存放接收到的等待分配的数据,以及一个用于存放等待传输的数据的队列。

    3、对于TCP套接字,还包含了与打开和关闭TCP握手相关的额定协议状态信息。

    了解这些数据结构,以及底层协议如何对其进行影响是非常有用的,因为它们控制了各种Socket对象行为的各个方面。例如,由于TCP提供了一种可信赖的字节流服务,任何写入Socket和OutpitStream的数据副本都必须保留,直到连接的另一端将这些数据成功接收。向输出流写数据并不意味着数据实际上已经被发送——它们只是被复制到了本地缓冲区,就算在Socket的OutputStream上进行flush()操作,也不能保证数据能够立即发送到信道。此外,字节流服务的自身属性决定了其无法保留输入流中消息的边界信息。

    数据传输的底层实现

在使用TCP套接字时,需要记住的最重要的一点是:不能假设在连接的一端将数据写入输出流和在另一端从输入流读出数据之间有任何的一致性。尤其是在发送端由单个输出流的write()方法传输的数据,可能会通过另一端的多个输入流的read()方法获取,而一个read()方法可能会返回多个write()方法传输的数据。

    一般来讲,我们可以认为TCP连接上发送的所有字节序列在某一瞬间被分成了3个FIFO队列:

    1、SendQ:在发送端底层实现中缓存的字节,这些字节已经写入输出流,但还没在接收端成功接收。它占用大约37KB内存。

    2、RecvQ:在接收端底层实现中缓存的字节,这些字节等待分配到接收程序——即从输入流中读取。它占用大约25KB内存。

    3、Delivered:接收者从输入流已经读取到的字节。

 当我们调用OutputStream的write()方法时,将向SendQ追加字节。

    TCP协议负责将字节按顺序从SendQ移动到RecvQ。这里有重要的一点需要明确:这个转移过程无法由用户程序控制或直接观察到,并且在块中发生,这些块的大小在一定程度上独立于传递给write()方法的缓冲区大小。

    接收程序从Socket的InputStream读取数据时,字节就从RecvQ移动到Delivered中,而转移的块的大小依赖于RecvQ中的数据量和传递给read()方法的缓冲区的大小。

   示例分析

     为了展示这种情况,考虑如下程序:

     其中,圆点代表了设置缓冲区数据的代码,但不包含对out.write()方法的调用。这个TCP连接向接收端传输8000字节,在连接的接收端,这8000字节的分组方式取决于连接两端的out.write()方法和in.read()方法的调用时间差,以及提供给in.read()方法的缓冲区的大小。

    下图展示了3次调用out.write()方法后,另一端调用in.read()方法前,以上3个队列的一种可能状态。不同的阴影效果分别代表了上文中3次调用write()方法传输的不同数据:

     现在假设接收者调用read()方法时使用的缓冲区数组大小为2000字节,read()调用则将把RecvQ中的1500字节全部移动到数组中,返回值为1500。注意,这些数据中包含了第一次和第二次调用write()方法时传输的字节,再过一段时间,当TCP连接传完更多数据后,这三部分的状态可能如下图所示:

     如果接收者现在调用read()方法时使用4000字节的缓冲区数组,将有很多字节从RecvQ队列转移到Delivered队列中,这包括第二次调用write()方法时剩下的1500字节加上第三次调用write()方法的钱2500字节。此时,队列的状态如下图:

     下次调用read()方法返回的字节数,取决于缓冲区数组的大小,亦及发送方套接字通过网络向接收方实现传输数据的时机。数据从sendQ到RecvQ缓冲区的移动过程对应用程序协议的设计有重要的指导性。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容