上面已经分别介绍了ServerSocket跟Socket的工作步骤,并且从应用层往系统底层剖析其运作原理,我们清楚了他们各自的一块,现在我们将把他们结合起来,看看他们是如何通信的,并详细讨论一下他们之间相互通信的一些细节。

借助图2-3-2-4,想象一下你正在大学课室上着电脑,你跟你另外两个朋友觉得老师讲得课很菜,没必要听,于是你们仨都各自打开浏览器冲浪,刚好你们访问了同一台服务器,假如你用的是浏览器A,那么整个流程为:

① 浏览器确认目标IP跟目标端口号(http默认使用80端口),当然如果你在浏览器地址栏输入带端口的地址,那么目标端口号将是你指定的端口,另外浏览器还将组织http报文,一并将这些参数传入系统底层socket。

② 系统层socket对TCP/IP协议的操作,从前面我们已经学到,一层一层往下其实就是将报文一层一层包起来,所以这里是先用http报文组织成TCP报文,再组织成IP报文,其中socket的源端口是随机分配的(一个大于1023随机数),最后放到TCP/IP栈里,排队发送消息。

③ ServerSocket正在堵塞监听接收连接,客户端socket与之建立连接。

④ 服务器端根据客户端请求创建socket,此socket即可用于跟客户端socket进行通信。

⑤ 服务器处理相关逻辑,例如数据库操作,逻辑判断等等。

⑥ 服务器处理完,行成相应的用于客户端浏览器显示的http报文,http报文经过tcp跟ip协议包装,返回给客户端socket。

⑦ 客户端经过层层解析,把http报文传到浏览器,浏览器对http报文进行解析,最后一个漂亮整洁的网页展示在你眼前。

⑧ 释放关闭连接。

如果你们仨在同一时间访问,服务器为了能有更好地性能,为了几乎同一时间响应你们,而不是一个处理完才处理另外一个,服务器会采取多线程处理,一个线程处理一个请求。

 

图2-3-2-4 ServerSocket与Socket通信模型





上面的通信模型从较宏观的层面描述了socket之间的通信,而在通信过程中必然涉及数据报文的传输,接着将学习socket底层数据的传输模型。图2-3-2-5形象地展现了数据是怎样从应用层到系统底层,再到互联网传输的。首先先介绍两个FIFO队列:SendQ跟RecvQ。它们都处于系统底层,在传输过程中充当缓冲区的作用,SendQ是把应用层发送到系统底层的数据进行缓冲,然后排队发送到因特网的队列,而RecvQ则是把从因特网接收到的数据进行缓冲,等待应用层去读取的队列。具体步骤如下:

① 应用层的Socket或Serversocket把要发送的数据写入系统底层的SendQ队列。

② SendQ队列根据先进先出原则,把这些数据发往因特网,到达目标主机。(从传输层来看,可以认为这时的数据是TCP报文)

③ 如果有数据从因特网发送过来,首先会被接收到RecvQ队列进行缓冲。

④ 应用层的Socket或Serversocket会循环尝试读取RecvQ队列,如果有数据则读取到应用层。

从中可以总结,TCP协议其实就是负责将数据按顺序从SendQ与RecvQ之间互相转移。而且从我们应用层来看这个转移过程我们是没有办法控制或直接观察的。同时,由于TCP提供可靠的数据传输服务,所以任何写入SendQ队列的数据都必须要保留一份数据副本,直到连接的另外一端成功接收。另外,Socket通过输出流向SendQ写数据并不意味着数据已经被发送,他们仅仅只是到了缓冲区,就算Socket的输出流进行了flush()操作也不能保证数据马上被发送到信道。

 

图2-3-2-5 socket数据传输模型





那么我们能不能就认为在连接的一端写入数据,另外一端就能马上读取数据呢?接着我们将更深入探讨SendQ与RecvQ队列里面的数据是怎样传输的,这个过程应该说是以块来传输的,而这些块的大小在一定程度上独立于应用层socket读写的缓冲大小。

如图2-3-2-6,假如应用层socket调用输出流write()方法向SendQ队列写数据,三次写入的数据大小分别为1000字节、2000字节、5000字节,而假设SendQ队列的缓存块大小为3000字节,第一次1000字节加上2000字节刚好等于3000字节,那么这两次的数据作为一个块进行传输。通过因特网到达RecvQ队列,应用层socket再通过输入流的read()方法读取RecvQ里的数据,输入流缓冲区读取了RecvQ队列3000字节就返回值3000。

 

图2-3-2-6 socket底层的块传输

在现实使用中,SendQ跟RecvQ队列可能会被无限填充, 为了防止一个TCP连接将系统内存全部耗尽,必须要对SendQ跟RecvQ队列的大小进行限制。一旦RecvQ队列数达到最大值,TCP流控制就会通知SendQ先停止发送数据,等我的RecvQ中的数据被socket输入流读走了有空间了再传给我。这样就能有效地控制过量发送,有效杜绝超出系统接收处理能力的情况。对于socket输出流可以不断写入数据,直到SendQ队列被填满了,此时write()方法将会阻塞等待。

喜欢研究java的同学可以交个朋友,下面是本人的微信号:

socket系列之socket服务端与客户端如何通信的更多相关文章

  1. (C#:Socket)简单的服务端与客户端通信。

    要求:1.可以完成一对一的通信:2.实现服务端对客户端一对多的选择发送:3.可以实现服务端的群发功能:4.可以实现客户端文件的发送: 要点:服务器端:第一步:用指定的端口号和服务器的ip建立一个End ...

  2. LinuxC语言实现服务端与客户端多进程通信

    链接:https://pan.baidu.com/s/1YDNIyTKAkh4E5x2dBeTgcQ 提取码:y35q 复制这段内容后打开百度网盘手机App,操作更方便哦 本实验用的是Centos7m ...

  3. 使用WebSocket实现服务端和客户端的通信

    开发中经常会有这样的使用场景.如某个用户在一个数据上做了xx操作, 与该数据相关的用户在线上的话,需要实时接收到一条信息. 这种可以使用WebSocket来实现. 另外,对于消息,可以定义一个类进行固 ...

  4. JAVA中Socket的用法模拟服务端和客户端

    <看透springMvc源代码分析与实践>学习笔记 Socket分为ServerSocket和Socket两个大类 ServerSocket用于服务端,可以通过accept方法监听请求,监 ...

  5. 一: WCF的服务端与客户端在通信时有三种模式:请求响应模式、数据报模式和双工通讯模式。

    说一下基本知识,  1.如果想要将当前接口作为wcf服务器,则一定要加上[ServiceContract] 契约 2.要想将方法作为wcf服务方法发布给外部调用,则一定要加上    [Operatio ...

  6. C# Socket服务端与客户端通信(包含大文件的断点传输)

    步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤:   (1)建立一个Socket   (2)接收 ...

  7. socket聊天室(服务端)(多线程)(TCP)

    #include<string.h> #include<signal.h> #include<stdio.h> #include<sys/socket.h&g ...

  8. C#服务端判断客户端socket是否已断开的方法

    刚开始,用Socket类的Connected属性来实现,却发现行不通,connected只表示  是在上次 还是 操作时连接到远程主机.如果在这之后[连接的另一方]断开了,它还一直返回true, 除非 ...

  9. Python3学习之路~8.3 socket 服务端与客户端

    通过8.2的实例1-6,我们可以总结出来,socket的服务端和客户端的一般建立步骤: 服务端 步骤:1创建实例,2绑定,3监听,4阻塞,5发送&接收数据,6关闭. #Author:Zheng ...

随机推荐

  1. [SDOI2016]硬币游戏

    题目描述 Alice 和 Bob 现在在玩的游戏,主角是依次编号为 1 到 n 的 n 枚硬币.每一枚硬币都有两面,我们分别称之为正面和反面.一开始的时候,有些硬币是正面向上的,有些是反面朝上的.Al ...

  2. [Wc2010]重建计划

    Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...

  3. 计蒜客NOIP模拟赛(3) D1T2 信息传递

    一个数据包在一个无向网络中传递.在时刻0,该数据包将依照特定的概率随机抵达网络中的某个节点.网络可以看做一张完全带权无向图,包含N个节点,若t时刻数据包在节点i,则在t+1时刻,数据包被传递到节点j的 ...

  4. [Apio2012]dispatching 左偏树

    题目描述 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增 ...

  5. 基于SSM框架实现简单的登录注册

    一.环境配置 工程目录 在pom.xml添加依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=& ...

  6. Spring MVC - 静态页面

    环境搭建 以下示例显示如何使用Spring MVC Framework编写一个简单的基于Web的应用程序,它可以使用<mvc:resources>标记访问静态页面和动态页面.首先使用Int ...

  7. Java正则过滤

    import java.util.regex.Matcher; import java.util.regex.Pattern; public class LongStringtonumber { pu ...

  8. git遇到的问题

    push代码时出现的问题: ! [remote rejected] HEAD -> (unpacker error)) 解决办法: $ git push --no-thin origin rel ...

  9. ftp:connect:未知错误号

    Linux下使用ftp命令时,提示:ftp: connect :未知错误号解决方法:service iptables stop或/etc/rc.d/init.d/iptables stop

  10. [self init]

    在字典转模型中遇到了这样的代码: #import "HMAppInfo.h" @implementation HMAppInfo - (instancetype)initWithD ...