IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Socket网络 -> 正文阅读

[网络协议]Socket网络

?

?

?

1、什么是Socket?
	Socket套接字是应用层(用户进程)与运输层(tcp和udp)之间的软件抽象层,可以用来实现不同计算机之间的通信。具有实时性、
	长连接的特点,在设计模式中相当于门面模式。
2、Socket的使用流程?
	见图
3、什么是Tcp/Udp?
	就是一个运输层传输协议
4、Tcp和Udp的区别?
	1、Tcp是面向连接的协议,也就是在发送数据前,必须和对方建立可靠的连接。
	一个Tcp的链接必须经过三次握手才能连接,四次挥手关闭连接。
	2、Udp是一个非连接的协议,传输数据之前双方不建立连接。当它想传送时就简单的抓取来自
	应用程序的数据,并尽可能快的把它扔到网络上。
	3、Tcp保证数据的正确性,Udp可能丢包。
	4、Tcp保证数据的传输顺序,UdP不保证。
5、Tcp的三次握手和四次挥手?
	三次握手:
		客户端向服务器发送连接请求。
		服务器收到消息响应,向客户端进行确认。
		客户端在向服务器表示确认。
	这个过程是在客户端的connect()和服务器的Accept()函数中的。
	四次挥手:
		客户端发送中断请求。
		服务器得到消息,继续处理未处理完的资源。
		服务器处理完毕通知客户端可以断开。
		客户端收到确认信息,表示断开。
6、Tcp粘包分包问题的出现?如何解决?
	粘包:
	    所谓粘包就是通讯的一端一次性连续发送多条数据包,tcp协议会将多个数据包打包成一个报文发 
        送出去。
		产生原因:
			1、要发送的数据小于Tcp发送缓冲区的大小。
			2、数据发送过快,导致数据包堆积多个数据后才一次性发送。
		解决方法:
			1、客户端在发送数据包的时候采用包头+包体的方式,包头表示上包体的长度,服务器接收后    
            根据长度来解析包体。
			2、将每个数据包封装成固定的长度,不够的用0填充。
			3、可以在数据包中设置特殊符号,接收端通过特殊符号来拆分
	拆包:
		就是通讯的一端发送的数据包超过tcp报文所能传输的最大值,就会将一个数据包拆分成多个数据            
        包分开传输。
		产生原因:
			1、传输数据大于tcp传输最大值
		解决方法:	
			1、也是传输数据包的时候加上数据的长度,,服务端接收到数据后,先读取四个字节的int 
        值,然后再读取对应长度的字节数。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Frame.Utility;

namespace NetFrame
{
    public class NetFrame
    {
        public class ServerFram : Singleton<ServerFram>
        {
            //服务端套接字对象
            public Socket serverSocket;

            //服务端回调
            private Action<string> serverCallback;

            //服务端消息缓存
            private byte[] serverBuffer;

            public ServerFram()
            {
            }

            /// <summary>
            /// 启动服务器
            /// </summary>
            /// <param name="servrCallback"></param>
            public void StartServer(Action<string> servrCallback)
            {
                //接收回调
                this.serverCallback = servrCallback;

                //实例化套接字
                //1.地址族 ipv4地址
                //2.套接字类型 读写流
                //3.协议类型 TCP
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                serverCallback("服务器套接字创建成功");

                serverCallback("da");
                
                //创建网络节点
                EndPoint endPoint = new IPEndPoint(IPAddress.Any, 23456);

                //绑定网络节点
                serverSocket.Bind(endPoint);

                serverCallback("服务器套节点绑定成功");

                //设置监听队列长度
                serverSocket.Listen(30);

                //开启异步接受
                serverSocket.BeginAccept(ServerAccept, serverSocket);
            }

            /// <summary>
            /// 服务器接收信息
            /// </summary>
            /// <param name="ar"></param>
            private void ServerAccept(IAsyncResult ar)
            {
                //获取到结果中的套接字对象
                Socket workingSocket = ar.AsyncState as Socket;
                //完成接受
                Socket acceptedSocket = workingSocket.EndAccept(ar);


                serverCallback("完成客户端连接:" + acceptedSocket.RemoteEndPoint);
                serverCallback("开启异步接受消息");


                serverBuffer = new byte[1024];

                //直接开始异步接收消息
                acceptedSocket.BeginReceive(
                    serverBuffer, //1.消息缓存
                    0, //2.起始位
                    serverBuffer.Length, //3.读取长度
                    SocketFlags.None, //4.不做特殊标记
                    ServerReceive, //5.收到信息的回调
                    acceptedSocket); //6.状态

                //开启尾递归
                serverSocket.BeginAccept(ServerAccept, serverSocket);
            }

            /// <summary>
            /// 收到信息
            /// </summary>
            /// <param name="ar"></param>
            private void ServerReceive(IAsyncResult ar)
            {
                Socket workingSocket = ar.AsyncState as Socket;

                //结束接收,返回长度
                int count = workingSocket.EndReceive(ar);

                serverCallback($"接收到{count}个字节的消息");

                //将消息编码形成字符串
                string msg = UTF8Encoding.UTF8.GetString(serverBuffer);

                serverCallback($"收到的消息是{msg}");

                //清空缓存
                serverBuffer = new byte[1024];

                //尾递归
                workingSocket.BeginReceive(serverBuffer, 0, serverBuffer.Length, SocketFlags.None,
                    ServerReceive, workingSocket);
            }

            /// <summary>
            /// 关闭服务器
            /// </summary>
            public void ServerShutDown()
            {
                //关闭套接字
                try
                {
                    serverSocket.Shutdown(SocketShutdown.Both);
                }
                finally
                {
                    serverSocket.Close();
                }
            }
        }

        public class ClientFrame : Singleton<ClientFrame>
        {
            private ClientFrame()
            {
            }

            private Socket clientSocket;

            private byte[] clientBuffer;

            private Action<string> clientCallback;

            /// <summary>
            /// 连接服务器
            /// </summary>
            /// <param name="serverIp"></param>
            /// <param name="serverPort"></param>
            /// <param name="clientCallBack"></param>
            public void ConnectToServer(string serverIp, int serverPort, Action<string> clientCallBack)
            {
                //赋值回调
                this.clientCallback = clientCallBack;

                //实例化客户端套接字
                clientSocket = new Socket(
                    AddressFamily.InterNetwork, //地址族
                    SocketType. Stream,//读写流
                    ProtocolType.Tcp); //TCP

                clientCallback("客户端套接字创建成功!");

                //连接服务器
                clientSocket.BeginConnect(IPAddress.Parse(serverIp), serverPort,
                    ClientConnect, clientCallBack);
            }

            /// <summary>
            /// 客户端连接
            /// </summary>
            /// <param name="ar"></param>
            private void ClientConnect(IAsyncResult ar)
            {
                Socket workingSocket = ar.AsyncState as Socket;

                //连接成功
                workingSocket.EndConnect(ar);

                clientCallback("连接服务器成功!");
            }

            /// <summary>
            /// 客户端发送信息
            /// </summary>
            /// <param name="msg"></param>
            public void ClientSendMsg(string msg)
            {
                //将字符串消息转换到buffer
                clientBuffer = UTF8Encoding.UTF8.GetBytes(msg);

                clientCallback("客户端正在发送消息:" + msg);

                //异步发送
                clientSocket.BeginSend(clientBuffer, 0, clientBuffer.Length,
                    SocketFlags.None, ClientSend, clientSocket);
            }

            /// <summary>
            /// 客户端发送
            /// </summary>
            /// <param name="ar"></param>
            private void ClientSend(IAsyncResult ar)
            {
                Socket workingSocket = ar.AsyncState as Socket;

                int count = workingSocket.EndSend(ar);

                clientCallback($"客户端发送消息成功「{count}」");
            }

            /// <summary>
            /// 关闭客户端
            /// </summary>
            public void CloseClient()
            {
                try
                {
                    clientSocket.Shutdown(SocketShutdown.Both);
                }
                finally
                {
                    clientSocket.Close();
                }
            }
        }
    }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NetFrameTest : MonoBehaviour
{
    public GUISkin skin;

    //0:未联网,1:服务器端,2:客户端
    private int netState = 0;
    
    private void OnGUI()
    {
        GUI.skin = skin;

        switch (netState)
        {
            case 0:
                OriginState();
                break;
            case 1:
                ServerState();
                break;
            case 2:
                ClientState();
                break;
        }
    }

    private string serverLog,clientLog;
    private string ipInput = "127.0.0.1", portInput = "23456";
    
    /// <summary>
    /// 初始状态
    /// </summary>
    private void OriginState()
    {
        GUILayout.Label("服务器端IP:");
        ipInput = GUILayout.TextField(ipInput);
        GUILayout.Label("服务器端Port:");
        portInput = GUILayout.TextField(portInput);

        if (GUILayout.Button("创建服务器"))
        {
            NetFrame.NetFrame.ServerFram.
                GetInstance().StartServer(
                    (msg) =>
                    {
                        serverLog += msg + "\n";
                    });
            netState = 1;
        }
        if (GUILayout.Button("连接服务器"))
        {
            NetFrame.NetFrame.ClientFrame.
                GetInstance().ConnectToServer(
                    ipInput,int.Parse(portInput),
                    (msg) =>
                    {
                        clientLog += msg + "\n";
                    });
            netState = 2; 
        }
    }
    
    Vector2 scrollViewValue = Vector2.zero;
    
    /// <summary>
    /// 服务状态
    /// </summary>
    private void ServerState()
    {
        scrollViewValue = GUILayout.BeginScrollView(scrollViewValue);
        GUILayout.Label(serverLog);
        GUILayout.EndScrollView();
    }

    private string clientSendMsg = "";
    
    /// <summary>
    /// 客户端状态
    /// </summary>
    private void ClientState()
    {
        GUILayout.Label("请输入要发送的消息:");
        clientSendMsg = GUILayout.TextField(clientSendMsg);
        if (GUILayout.Button("发送"))
        {
            NetFrame.NetFrame.ClientFrame.GetInstance().
                ClientSendMsg(clientSendMsg);
        }

        scrollViewValue = GUILayout.BeginScrollView(scrollViewValue);
        GUILayout.Label(clientLog);
        GUILayout.EndScrollView();
    }

    private void OnApplicationQuit()
    {
        if(netState == 1)
            NetFrame.NetFrame.ServerFram.GetInstance().ServerShutDown();
        else if(netState == 2)
            NetFrame.NetFrame.ClientFrame.GetInstance().CloseClient();
    }
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-10-21 12:46:40  更:2021-10-21 12:48:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:26:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码