栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Socket网络

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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
        {
            //服务端套接字对象
            public Socket serverSocket;

            //服务端回调
            private Action serverCallback;

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

            public ServerFram()
            {
            }

            /// 
            /// 启动服务器
            /// 
            /// 
            public void StartServer(Action 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);
            }

            /// 
            /// 服务器接收信息
            /// 
            /// 
            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);
            }

            /// 
            /// 收到信息
            /// 
            /// 
            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);
            }

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

        public class Clientframe : Singleton
        {
            private Clientframe()
            {
            }

            private Socket clientSocket;

            private byte[] clientBuffer;

            private Action clientCallback;

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

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

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

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

            /// 
            /// 客户端连接
            /// 
            /// 
            private void ClientConnect(IAsyncResult ar)
            {
                Socket workingSocket = ar.AsyncState as Socket;

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

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

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

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

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

            /// 
            /// 客户端发送
            /// 
            /// 
            private void ClientSend(IAsyncResult ar)
            {
                Socket workingSocket = ar.AsyncState as Socket;

                int count = workingSocket.EndSend(ar);

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

            /// 
            /// 关闭客户端
            /// 
            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";
    
    /// 
    /// 初始状态
    /// 
    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;
    
    /// 
    /// 服务状态
    /// 
    private void ServerState()
    {
        scrollViewValue = GUILayout.BeginScrollView(scrollViewValue);
        GUILayout.Label(serverLog);
        GUILayout.EndScrollView();
    }

    private string clientSendMsg = "";
    
    /// 
    /// 客户端状态
    /// 
    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();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/337277.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号