计算机网络再次整理————tcp例子[五]
前言
本文介绍一些tcp的例子,然后不断完善一下。
正文
服务端:
// See https://aka.ms/new-console-template for more information
using System.Net;
using System.Net.Sockets;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Bind(endPoint);
socket.Listen();
while (true)
{
Console.WriteLine("开始接收");
var clientSocket = socket.Accept();
Console.WriteLine("接收到消息");
var receiveMessage = new Byte[1000];
clientSocket.Receive(receiveMessage);
Console.WriteLine("receive message is:"+System.Text.Encoding.UTF8.GetString(receiveMessage));
clientSocket.Close();
}
客户端:
using System.Net;
using System.Net.Sockets;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Connect(endPoint);
socket.Send(System.Text.Encoding.UTF8.GetBytes("hello service"));
socket.Send(System.Text.Encoding.UTF8.GetBytes("hello service2"));
Console.WriteLine("发送成功");
Console.ReadLine();
服务端打印:

可以看客户端发送了两次,但是服务端一次就读取出来了,这就是著名的粘包。
为什么会有粘包这个现象呢?首先来分析一下这个粘包的原因,抓包即可。
看到第一次发送的包:

看到第二次发送的包:

看来跟客户端没有关系了。
这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。
那么有没有可能粘包是客户端造成的,或者说发送方造成的?当然也是很多有可能的,这里就不作演示,单纯的理论一下。
TCP 协议是面向连接的、可靠的、基于字节流的传输层通信协议,应用层交给 TCP 协议的数据并不会以消息为单位向目的主机传输,这些数据在某些情况下会被组合成一个数据段发送给目标的主机。
比如说nagle 算法:
Nagle 算法是一种通过减少数据包的方式提高 TCP 传输性能的算法。因为网络 带宽有限,它不会将小的数据块直接发送到目的主机,而是会在本地缓冲区中等待更多待发送的数据,这种批量发送数据的策略虽然会影响实时性和网络延迟,但是能够降低网络拥堵的可能性并减少额外开销。
在早期的互联网中,Telnet 是被广泛使用的应用程序,然而使用 Telnet 会产生大量只有 1 字节负载的有效数据,每个数据包都会有 40 字节的额外开销,带宽的利用率只有 ~2.44%,Nagle 算法就是在当时的这种场景下设计的。
当应用层协议通过 TCP 协议传输数据时,实际上待发送的数据先被写入了 TCP 协议的缓冲区,如果用户开启了 Nagle 算法,那么 TCP 协议可能不会立刻发送写入的数据,它会等待缓冲区中数据超过最大数据段(MSS)或者上一个数据段被 ACK 时才会发送缓冲区中的数据。
除了 Nagle 算法之外,TCP 协议栈中还有另一个用于延迟发送数据的选项 TCP_CORK,如果我们开启该选项,那么当发送的数据小于 MSS 时,TCP 协议就会延迟 200ms 发送该数据或者等待缓冲区中的数据超过 MSS。
无论是 TCP_NODELAY 还是 TCP_CORK,它们都会通过延迟发送数据来提高带宽的利用率,它们会对应用层协议写入的数据进行拆分和重组,而这些机制和配置能够出现的最重要原因是 — TCP 协议是基于字节流的协议,其本身没有数据包的概念,不会按照数据包发送数据。
好了,现在知道了粘包问题了。
上面这段代码还有另外一个问题,那就是比如我们传输1个G的数据,那么操作系统会帮我们分成很多个包进行拆分。
比如1g数据分成了100个包了,接收方没有接收完,就调用了读取。这时候又该怎么处理呢?我是读取到了50个包的时候完成了,还是读取80个包的时候完成了。
这些就是应用协议应该解决的问题了。
我们知道数据链路层通过再数据前后增加标识符来变成帧来识别一段数据的。
而网络层,如果是比较大的包,那么路由器会进行拆包,但是包里面标记了序号,同样标记了每个包的大小,和总包的大小。(ip报文分片)
首先tcp是按顺序传输的,这样呢,我们就不用标记序号了,那么就有两个选择了:
- 在数据前后标记,这样便于分割或者组合
- 在数据里面增加消息的大小,比如说有缓存了100个字节,前面4个字节表示后面消息的大小
要真正的写好这两个还是比较多code的,后面找个时间补充。而且网上例子挺多的。
可以去搜tcp数据无边界问题,不一定只搜粘包问题,比如说发送1G数据,到底什么时候才算收完,这就不叫粘包了,但是属于tcp无数据边界问题。
当然了粘包给出的方案也解决了数据无边界的问题。
结
下一节,简单介绍一下udp吧。很多问题,其实在以前的网络编程系列中提及到了,后面依然会整理,可能会反复整理几次。
计算机网络再次整理————tcp例子[五]的更多相关文章
- 计算机网络再次整理————tcp例子前奏[三]
前言 简单编写一下tcp例子. 正文 我们常说IOS有7层,实际上也只有4层,或者这样说简单的说是4层. 首先是数据链路层,首先这一层解决了什么问题呢?为什么要有这一层呢? 首先要抛开有操作系统的意识 ...
- 计算机网络再次整理————tcp例子第二前奏[四]
前言 前文我们介绍了网络协议的各层,同时也介绍了一下我们在编写代码时候的服务端的accept.bind.listen.connect.send做了什么. 可以说是从宏观的角度,或者代码开发的角度来说的 ...
- 计算机网络再次整理————tcp周边[八]
前言 tcp的包的格式可以看我以前的计算机网络整理,下面这些周边只是为了开发时候我们能用到一些理论知识. 正文 首先要介绍的就是域名,为啥有域名这东西呢?单纯站在网络的角度上讲这属于应用层的东西了. ...
- 计算机网络再次整理————tcp[二]
前言 本文不会去介绍tcp的具体协议,因为这个tcp 应该不能说是单纯的连接和传输数据这么简单,里面还有很多机制. 正文 首先介绍一下什么是协议族(protocal Family),举个例子PF_IN ...
- 计算机网络再次整理————UDP例子[六]
前言 简单的说,UDP 没有 TCP 用的广泛,但是还有很多是基于UDP的程序的,故而简单介绍一下. 正文 秉承节约脑容量的问题,只做简单的介绍和例子,因为自己几乎也没怎么用过UDP. 只是了解和知晓 ...
- 计算机网络再次整理————tcp的关闭[七]
前言 tcp的关闭不是简单粗暴的,相对而言是友好优雅的,好聚好散吧. 那么友好的关闭方式是这样的: 假设这里是客户端请求关闭的,服务端倒过来. 客户端:我要请求关闭 服务端:我接收到你的请求了,等我把 ...
- 计算机网络再次整理————socket[一]
前言 以前也整理过吧,写了几篇之后,感觉没啥整理的必要了然后就放弃了,最近又想整理一下. 正文 这篇对应的是:https://www.cnblogs.com/aoximin/p/12235333.ht ...
- 计算机网络基础之TCP/IP 协议栈
计算机网络基础之TCP/IP 协议栈 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.TCP/IP 协议栈概述 1>.什么是TCP/IP协议栈 Transmission C ...
- 计算机网络知识之TCP/IP协议簇
OSI参考模型 OSI的来源 OSI(Open System Interconnect),即开放式系统互联. 一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网 ...
随机推荐
- CODEFORCEs 621E. Wet Shark and Blocks
E. Wet Shark and Blocks time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- Codeforces 777C:Alyona and Spreadsheet(预处理)
During the lesson small girl Alyona works with one famous spreadsheet computer program and learns ho ...
- 【C++】leetcode竞赛笔记
*注--代码非博主本人所写,仅供学习参考,侵删 20200516双周赛: 1 to_string(int a) 将a转换成字符串形式 2 gcd(int a,int b) 返回a,b的最大公约数,若 ...
- Differential Evolution: A Survey of the State-of-the-Art
@ 目录 概 主要内容 DE/rand/1/bin DE/?/?/? DE/rand/1/exp DE/best/1 DE/best/2 DE/rand/2 超参数的选择 的选择 的选择 的选择 一些 ...
- 详解Kalman Filter
中心思想 现有: 已知上一刻状态,预测下一刻状态的方法,能得到一个"预测值".(当然这个估计值是有误差的) 某种测量方法,可以测量出系统状态的"测量值".(当然 ...
- Java Swing设计简单商品信息管理系统(java swing+mysql+eclipse)
一.概述 为了管理好商店库存信息,提升店铺管理工作效率,结合实际工作需要,设计和开发本系统,主要用于商店商品信息维护出入库等.包含商品库存信息查看.商品信息修改,新增商品信息,删除信息等功能. 二.功 ...
- oracle 之 for循环表
代码 create table tm_lzh as SELECT 'a1' c1,'b1' c2 FROM dual union all SELECT 'a2' c1,'b2' c2 FROM dua ...
- 使用 Docker 部署 Seata Server(分布式事务解决方式)
1.获取镜像 ## 使用下面命令获取最新版本的镜像,此时我的版本是1.3.0 ## 或者可以使用docker pull seataio/seata-server:latest获取最新的镜像 docke ...
- Centos7下yum安装mydql8
昨天安装mydql时总是报错缺少插件,虽然最后安装上了,但还是在此记录下 一. 安装centos7系统系统 在选择安装基本环境时,选择基本环境为"网页服务器",昨天我因为选择了&l ...
- nginx配置图片路径
首先, 在linux下创建你存放资源的目录,例如:/data/images:用于存放图片. 下一步,打开default.conf配置文件找到server块下的location添加如下 location ...