TCP 学习笔记

news2025/4/11 13:44:04

Win + R   打开控制台输入CMD  打开小黑窗, 输入ipconfig  查询本机地址

 

“外网IP是全世界唯一的IP地址,仅分配给一个网络设备。而内网IP是由路由器分配给每一部内部使用的IP地址,而内网的所有用户都是通过同一个外网IP地址进行上网的,而内网的IP地址每个人的都不一样,Internet上的用户也无法直接访问到内网用户。简单来说呢,外网IP就是标示了您在整个互联网上的地址,就相当于小区的地址,而内网IP呢,就是标识着您在局域网里面的地址,也就是小区内的几栋几楼几号房子。

内网IP地址一般是192.168开头 ,连接到wifi或网线的每个设备都有自己的一个内网ip

外网可以理解为公司的总网,也就是牵的网线里的网络

而内网是由路由器为每个设备分配的ip

端口号就是用来决定将消息传给同一内网IP下的某个程序 

三次握手,四次挥手

TCP 协议比较稳定,需要与接收方建立连接,可以确保数据不会丢失,可以保证数据发送的是否正确,需得到接收方的返回,如果在一定时间内没有收到回应则会重新发送。

UDP 速度快,但是不稳定安全,不用建立连接 (只管发,不管接,可能会被拦截,或断掉)

三次握手: 建立连接

四次挥手:断开连接

 IPv6的出现是因为IPv4不够用了 

 

 TCP 用Stream 流通信比较稳定,  创建服务端代码如下

using System.Net.Sockets;
using System.Net;
namespace TCP学习
{
    class Program
    {
        static void Main(string[] args)
        {
            StartServerAsync();
            Console.ReadKey();
        }
        static void StartServerAsync()
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //本机IP: 192.168.1.195 /127.0.0.1(127永远代表本机IP)  //196不是固定的,重启后或一定时间后路由器会重新分配IP
            //IPAddress xxx.xxx.xxx.xxx  IPEndPoint xxx.xxx.xxx.xxx:port
            //IPAddress iPAddress = new IPAddress(new byte[] { 192, 168, 1, 195 });
            IPAddress iPAddress = IPAddress.Parse("192.168.1.195");//推荐
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 88);
            serverSocket.Bind(iPEndPoint); //绑定IP和端口号
            serverSocket.Listen(0);   //开始监听端口号,参数为监听队列长度,
                                      //Listen(10)指超过10个后的消息不接收,设置为0不限制

            //同步接收客户端的连接(旧方法)
            //Socket clientSocket = serverSocket.Accept(); // 接收一个客户端链接 程序在这里暂停,直到有客户端连接
            //向链接的客户端发送消息
            //string msg = "Hello你好";
            //byte[] msgB = System.Text.Encoding.UTF8.GetBytes(msg); //把字符串转为字节数组
            //clientSocket.Send(msgB);
            //dataBuffer = new byte[10240];

            //异步接收客户端的消息,不影响下面的代码执行//当接收到客户端消息时才调用回调方法,最后一个参数是回调方法的参数
            //clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);


            //同步接收客户端的消息(旧方法)
            //byte[] msgC = new byte[1024];
            //int count = clientSocket.Receive(msgC); //用msgC储存接收的数据.//程序在这里暂停,等待客户端发送消息//返回值是接收到的数据的长度
            //string msgD = System.Text.Encoding.UTF8.GetString(msgC, 0, count); //把前count个的字节数组数据转为字符串                                                           //从0开始读取count个数据
            //Console.WriteLine(msgD);

            //Console.ReadKey();
            //clientSocket.Close(); //关闭的和客户端的一个连接
            //serverSocket.Close(); //关闭自身的连接,停服

            serverSocket.BeginAccept(AcceptCallBack, serverSocket);

            //到目前为止 服务器端已经可以处理多个客户端的连接,也可以处理多个来自同一个客户端的消息 最终处理来自多个客户端的多个消息
        }
        static byte[] dataBuffer = new byte[1024];

        static void AcceptCallBack(IAsyncResult ar)
        {
            Socket serverSocket = ar.AsyncState as Socket;
            Socket clientSocket = serverSocket.EndAccept(ar);
            string msg = "Hello你好";
            byte[] msgB = System.Text.Encoding.UTF8.GetBytes(msg);
            clientSocket.Send(msgB);
            clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);
            serverSocket.BeginAccept(AcceptCallBack, serverSocket);
        }
        static void ReceiveCallBack(IAsyncResult ar)
        {
            Socket clientSocket = null;
            try    //try 异常捕捉是为了当客户端异常关闭(非正常关闭)时,让所持有的客户端被释放且无法用该客户端继续接收消息
            {
                clientSocket = (Socket)ar.AsyncState;
                int count = clientSocket.EndReceive(ar);  //客户端如果发送"" 是接收不到的,当客户端Close时,会收到客户端的空消息,个数为0
                //所以当客户端的消息个数为0时,客户端主动断开(正常关闭)了
                if (count == 0)
                {
                    clientSocket.Close();
                    return;
                }
                string msg = System.Text.Encoding.UTF8.GetString(dataBuffer, 0, count);
                Console.WriteLine("从客户端接收到数据:" + msg);
                clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                if (clientSocket != null)
                {
                    clientSocket.Close();
                }
            }
            finally
            {
               
            }
        }
    }
    
}

创建客户端代码如下

using System.Net.Sockets;
using System.Net;
namespace TCP客户端
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //客户端只需要和服务端建立连接 ,不需要绑定Bind
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientSocket.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.195"),88));
            //接收这部分和服务器端一样
            byte[] msgC = new byte[1024];
            int count = clientSocket.Receive(msgC); //接收服务端的消息,用msgC储存接收的数据.
                                                    //返回值是接收到的数据的长度
                                                    // 执行到Receive程序会暂停,直到接收到服务端的消息 
            string msgD = System.Text.Encoding.UTF8.GetString(msgC, 0, count); //把前count个的字节数组数据转为字符串
                                                                               //从0开始读取count个数据
            Console.WriteLine(msgD);

            while (true)
            {
                string str = Console.ReadLine();
                if (str == "Close")   //客户端发送Close 主动要求断开连接
                { 
                    clientSocket.Close();
                    return;
                }
                clientSocket.Send(System.Text.Encoding.UTF8.GetBytes(str));
            }
            Console.ReadKey();
            clientSocket.Close();
        }
    }
}

同步方式:Accept Connect   /   Receive

异步方式:BeginAccept  EndAccept  /    BeginReceive    EndReceive  

效果如下,多客户端连接一个服务器

粘包和分包

粘包 :当发送数据比较频繁,且数据量小,TCP  在你点发送时不会立马把数据发出去,而是等很多条数据达到一定量整合到一起发出去,服务器端或客户端执行一次Receive就可以收到多条消息的整合,如果点一次发一次会造成数据传输性能开销,

 粘包虽然会粘在一起,但是到达的先后顺序是不会变的

分包: 当数据量很大,上千上万的数据,TCP会分几次发送,大包占用网速,运送慢, 占用时间长,发送失败还要重新发送,服务器端或客户端执行一次Receive可能收到的不是一个完整的消息,而是被分割的消息段

我们定义的数组是1024字节,所以一次消息只能发1024字节数据,数据超过了就要分包发送,

可以加大每次发送的字节容量大小来避免分包(前提是异步,如果是同步,即使容量大也会分包),不过一般不考虑,很少有一次会发送那么大的数据,应该考虑的是粘包问题,因为游戏交互每次发送数据的量很小。次数也多

 处理粘包问题:

一个字符占一个字节 ,一个空格占用一个字节 ,一个汉字占3个字节

  int count = 15686;
            byte[] data = BitConverter.GetBytes(count);//支持值类型参数
            foreach (byte b in data)
            {
                Console.Write(b + ":");  //可以确保数据头只占用int32  4个字节
            }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/677425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(四)WPF - 布局

一、布局过程 WPF 布局包括两个阶段:一个测量阶段和排列阶段 在测量阶段,容器遍历所有子元素,并询问子元素它们所期望的尺寸。在排列阶段,容器在合适的位置放置子元素。(每个元素都被其父元素告知它自己的尺寸是多少…

【软件设计师暴击考点】下午题高频考点暴击系列

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:软件…

电脑选购必备的六大技巧

目录 1、CPU方面 2、显卡方面 3、电脑主板方面 4、内存和硬盘方面 5、电脑机箱和电源方面 6、装机过程要全程参与 今天小编给大家分享电脑选购组装必备的六大技巧,希望对大家实际选购、组装电脑提供一些帮助! 买电脑要注意哪些问题 1、CPU方面 C…

Qt Model-View架构领悟

1.架构的选择 1.1是否需要委托 模型视图架构图如下所示,模型视图架构源于MVC模式:模型(Model)是应用对象,表示数据;视图(View)是模型的用户界面,用以显示数据&#xff…

springboot基础(78):Freemarker模板生成word文档

文章目录 前言如何使用Freemakrer生成word文档1. 制作模板2. 编写工具类 遇到的问题下载失败如何只生成文件不下载 前言 利用Freemarker模板生成word文档。示例,将左侧的模板生成为右侧的文档并下载。 如何使用Freemakrer生成word文档 1. 制作模板 1.编辑一份a…

实现注册与登录(企业级)

目录 实现注册超级管理员功能(持久层) 一、判定系统是否已经绑定超级管理员 二、编写保存用户记录的代码 三、编写查询用户ID的代码 实现注册超级管理员功能(业务层) 一、获取OpenId 二、编写注册新用户的业务代码 掌握 R…

tuple 和数组区别

元组(tuple)和数组(array)都是 Python 中用于存储多个值的数据结构,但它们在实现和使用上有一些区别。 元组是不可变的,而数组是可变的。即元组一旦创建,其内容就不能被修改,而数组…

高数笔记1(第一章函数 极限 连续 第一节函数第二节极限-极限的概念与性质)

目录 第一章 函数 极限 连续第一节 函数第二节 极限一、极限的概念与性质数列的极限例1例2 函数的极限极限的性质(保号性重点 有界性)例12例13例14 函数极限与数列极限的关系例15 第一章 函数 极限 连续 第一节 函数 判断有界要用函数的绝对值&#xff…

Toolformer:可以教会自己使用工具的语言模型

Toolformer:可以教会自己使用工具的语言模型 摘要Introduction现有大模型的局限处理办法本文的idea Approach样例化API调用执行API调用筛选API调用模型微调 实验局限 论文地址点这里 摘要 语言模型(LMs)呈现了令人深刻的仅使用少量的范例或…

2022(一等奖)D1649基于多源卫星遥感的干旱区农作物耗水精细模拟

作品介绍 1 研究背景及目标 1.1 研究区概况 本次研究的研究区位于甘肃省张掖市内。张掖市位于甘肃省西部,河西走廊中段,属干旱和半干旱两种气候类型,其特点是夏季短而酷热,冬季长而严寒,干旱少雨,且降水分…

MySQL-SQL存储过程/触发器详解(下)

♥️作者:小刘在C站 ♥️个人主页: 小刘主页 ♥️努力不一定有回报,但一定会有收获加油!一起努力,共赴美好人生! ♥️学习两年总结出的运维经验,以及思科模拟器全套网络实验教程。专栏&#xf…

ubuntu20.4服务器搭建ftp并连接(阿里云服务器)

首先在控制台添加ftp防火墙规则: 然后进入服务器安装ftp(安装vsftpd): sudo apt update sudo apt install vsftpd使用以下命令检查其状态: sudo service vsftpd status如果FTP服务器未运行,请使用以下命令启动它&am…

强化学习:时序差分算法 TD-learning

例子引入 首先,我们考虑简单的平均估计计算: w E [ X ] wE[X] wE[X],根据 RM算法 计算过程如下: 接着上面的例子,我们现在考虑一个较为复杂的问题,估计函数 v ( X ) v(X) v(X) 的平均值,根据 …

3.数据模型

文章目录 前言1.对象(Object)1.1 标准对象1.2 自定义对象1.2.1 创建一个property(房产)自定义对象1.2.2创建一个Favorite(收藏夹)自定义对象1.2.3 创建对象的注意事项 1.3 字段1.3.1 为property object创建…

迅镭激光参展CESC2023中国(江苏)国际储能大会,共话储能产业发展趋势!

2023年6月14日 中国(江苏)国际储能大会 暨智慧储能技术及应用展览会 在南京国际博览中心隆重开幕 迅镭激光携多款新能源解决方案 精彩亮相A区5C21展位 聚焦新能源电池绿色智能制造 共话储能行业创新发展之路 本次展会为期三天(6月14-16日) 诚邀广大行业同仁莅临参观交流! 本届大…

全志V3S嵌入式驱动开发(spi-nor驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 所谓的spi nor驱动,其实就是让spi nor芯片,在linux kernel 5.2.y启动后可以被正确地识别到。前面有一篇文章,我…

POSIX信号量(基于生产消费模型)

目录 🍊一、信号量 1.1之前代码的不足之处 1.2什么是信号量 🍊二、信号量接口 🍊三、信号量版本的生产消费模型 ①单生产单消费 ②多生产多消费 🍊四、线程池 🍊五、线程安全的单例模式 🍊六、其他常…

大模型高效微调综述下: DiffPruning、BitFit、LoRa、AdaLoRA、MAM Adapters、UniPELT

文章目录 四、Selective Methods4.1 DiffPruning(2020.10)4.2 BitFit(2021.6)4.3 Freeze and Reconfigure (FAR,2022)4.4 FishMask(略) 五、Reparametrization-based methods(重参数…

Selenium自动化工具集 - 完整指南和使用教程

文章目录 Selenium 的概述:Selenium 的安装与环境配置:Selenium WebDriver 的基本概念:定位元素的方法:常用操作方法:获取所有的 cookie:获取指定名称的 cookie:添加 cookie:删除指定…

JavaFX应用开发教程——基于JDK9与NetBeans实现

ISBN: 978-7-302-61499-9 作者:宋波 页数:257页 阅读时间:2023-06-18 推荐指数:★★★★★ 《JavaFX应用开发教程——基于JDK9与NetBeans实现》 是目前市面上讲解Java桌面开发为数不多的教材 (JavaFX是Java语言的下一代…