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 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Week 08-day01-Unity网络通讯之聊天室 -> 正文阅读

[游戏开发]Week 08-day01-Unity网络通讯之聊天室

目录

一、了解编写服务器demo?

?二、Demo一之中的不足:1.byte[1024]无内容部分都转成了空格,如何解决?2.客户端只能发送一条消息,如何解决?3.只能接受一个客户端发送的消息,如何改进?

?解决方法:

三:实现消息的广播

?四:改写成为异步服务器

思考:有没有问题呢?会不会出错呢?

五、Client类的封装

ClientPeer类

NetManager类:

main函数类:

六、动态链接库:


一、了解编写服务器demo?

基础知识:

? ? ? ? IP地址:计算机在网络中的位置
? ? ? ? DNS:将域名转化为对应IP地址的服务器
? ? ? ? 端口号:计算机某一个程序,在操作系统中的编号
? ? ? ? 协议:网络传输中的约定
? ? ? ? TCP:管道式传输
? ? ? ? ? ? ? ? 三次握手:
? ? ? ? ? ? ? ? 四次挥手:
? ? ? ? UDP:广播式传输

服务器端代码1.0:

using NetMQ.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace NetWorkTest
{
    //ip:计算机在网络中的位置
    //端口:计算机应用程序在操作系统中的编号
    //传输协议:TCP:管道式传输,好处:安全,信息的先后顺序保持不变;缺点:传输速度限制比较大
    //          UDP:广播式传输,好处:传输速度很快;缺点:安全性较低,丢包
    class Program
    {
        static void Main(string[] args)
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse("192.168.117.1");
            int port = 9999;     
            serverSocket.Bind(new IPEndPoint(ip,port));
            serverSocket.Listen(10);

            Console.WriteLine("服务器启动了!");
           
            Socket clientSocket = serverSocket.Accept();//这是一个阻塞函数
            Console.WriteLine("服务器收到了一个客户端连接"+clientSocket.RemoteEndPoint.ToString());

            Byte[] MsgArr = new Byte[1024];
            clientSocket.Receive(MsgArr, 0, MsgArr.Length, SocketFlags.None);
            string msg = Encoding.UTF8.GetString(MsgArr);
            Console.WriteLine("接受的数据为:"+msg);

            Console.ReadKey();
        }
    }
}

?客户端代码1.0:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ClientTestOne
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress iPAddress = IPAddress.Parse("192.168.117.1");
            int port = 9999;
            clientSocket.Connect(new IPEndPoint(iPAddress, port));
            Console.WriteLine("客户端开始连接服务器!");

            string content = "wo只会心疼哥哥!";
            byte[] msg = Encoding.UTF8.GetBytes(content);
            clientSocket.Send(msg);

            Console.ReadKey();
        }
    }
}

?二、Demo一之中的不足:
1.byte[1024]无内容部分都转成了空格,如何解决?
2.客户端只能发送一条消息,如何解决?
3.只能接受一个客户端发送的消息,如何改进?

思路:使用多线程

?解决方法:

1.

2.?

3.

服务端2.0

using NetMQ.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace NetWorkTest
{
    //ip:计算机在网络中的位置
    //端口:计算机应用程序在操作系统中的编号
    //传输协议:TCP:管道式传输,好处:安全,信息的先后顺序保持不变;缺点:传输速度限制比较大
    //          UDP:广播式传输,好处:传输速度很快;缺点:安全性较低,丢包
    class Program
    {
        static void Main(string[] args)
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse("192.168.117.1");
            int port = 9999;     
            serverSocket.Bind(new IPEndPoint(ip,port));
            serverSocket.Listen(10);

            Console.WriteLine("服务器启动了!");

            while (true)
            {
                Socket clientSocket = serverSocket.Accept();//这是一个阻塞函数
                Console.WriteLine("服务器收到了一个客户端连接" + clientSocket.RemoteEndPoint.ToString());
                Thread thread = new Thread(ReceiveMsg);
                thread.Start(clientSocket);
            }

            Console.ReadKey();
        }

        private static void ReceiveMsg(object obj)
        {
            Socket clientSocket = obj as Socket;
            byte[] MsgArr = new byte[1024];
            while (true)
            {
                int Length = clientSocket.Receive(MsgArr, 0, MsgArr.Length, SocketFlags.None);
                string msg = Encoding.UTF8.GetString(MsgArr, 0, Length);
                Console.WriteLine("接受的数据为:" + msg);
            }
        }
    }
}

客户端2.0

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace ClientTestOne
{
    class Program
    {
        static Socket clientSocket;
        static void Main(string[] args)
        {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress iPAddress = IPAddress.Parse("192.168.117.1");
            int port = 9999;
            clientSocket.Connect(new IPEndPoint(iPAddress, port));
            Console.WriteLine("客户端开始连接服务器!");

            Thread thread = new Thread(ReceiveMsg);
            thread.Start();
     
            while (true)
            {
                string content = Console.ReadLine();
                byte[] msg = Encoding.UTF8.GetBytes(content);
                clientSocket.Send(msg);

            }

            Console.ReadKey();
        }

        static void ReceiveMsg()
        {
            byte[] MsgArr = new byte[1024];
            while (true)
            {
                int Length = clientSocket.Receive(MsgArr, 0, MsgArr.Length, SocketFlags.None);
                string msg = Encoding.UTF8.GetString(MsgArr, 0, Length);
                Console.WriteLine("接受的数据为:" + msg);
            }
        }

    }
   
}

又出现一个小问题:只要有客户端关闭,服务器就会出错,那么如何改进这个问题呢?解决方式:需要使用try...catch

改进后的服务器2.0代码:

using NetMQ.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace NetWorkTest
{
    //ip:计算机在网络中的位置
    //端口:计算机应用程序在操作系统中的编号
    //传输协议:TCP:管道式传输,好处:安全,信息的先后顺序保持不变;缺点:传输速度限制比较大
    //          UDP:广播式传输,好处:传输速度很快;缺点:安全性较低,丢包
    class Program
    {
        static void Main(string[] args)
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse("192.168.117.1");
            int port = 9999;     
            serverSocket.Bind(new IPEndPoint(ip,port));
            serverSocket.Listen(10);

            Console.WriteLine("服务器启动了!");

            while (true)
            {
                Socket clientSocket = serverSocket.Accept();//这是一个阻塞函数
                Console.WriteLine("服务器收到了一个客户端连接" + clientSocket.RemoteEndPoint.ToString());
                Thread thread = new Thread(ReceiveMsg);
                thread.Start(clientSocket);
            }

            Console.ReadKey();
        }

        private static void ReceiveMsg(object obj)
        {
            Socket clientSocket = obj as Socket;
            byte[] MsgArr = new byte[1024];
            while (true)
            {
                try
                {
                    //receive的返回值,就是结束到的数据的长度,Receive()是一个阻塞函数
                    int Length = clientSocket.Receive(MsgArr, 0, MsgArr.Length, SocketFlags.None);
                    if (Length == 0)
                    {
                        clientSocket.Close();
                        return;

                    }
                    string msg = Encoding.UTF8.GetString(MsgArr, 0, Length);
                    Console.WriteLine("接受的数据为:" + msg);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    clientSocket.Close();
                    return;
                }
               
            }
        }
    }
}

?运行截图:

三:实现消息的广播

提示:客户端自己不需要给自己发消息,使用List存储客户端连接

服务端3.0

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;


namespace ChatServer
{
    class Program
    {
        //消息的广播:需要使用List容器存储与客户端建立的连接
        private static List<Socket> SocketPoolList = new List<Socket>();

        static void Main(string[] args)
        {
            try
            {
                //连接客户端
                Socket Serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                int port = 8899;
                IPAddress iPAddress = IPAddress.Parse("192.168.117.1");
                Serversocket.Bind(new IPEndPoint(iPAddress, port));
                Serversocket.Listen(10);

                Console.WriteLine("服务器启动了");

                //主线程中最好不要放置死循环的代码
                Thread thread = new Thread(AcceptClient);
                thread.Start(Serversocket);

              
                Console.ReadKey();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message); 
                
            }
            
           
        }

        //接收客户端连接
        private static void AcceptClient(object obj)
        {
            Socket Serversocket = obj as Socket;
            if (Serversocket == null)
            {
                return;
            }
            Socket ClientServer = Serversocket.Accept();
            SocketPoolList.Add(ClientServer);
            Console.WriteLine("服务器收到了一个连接:" + ClientServer.RemoteEndPoint.ToString());

            Thread thread = new Thread(ReceiveMsg);
            thread.Start(ClientServer);

            //服务器需要一直接受客户端的消息
            AcceptClient(Serversocket);
        }

        private static void ReceiveMsg(Object obj)
        {
            Socket ClientSocket = obj as Socket;
            if (ClientSocket == null)
            {
                return;
            }
            byte[] msgArr = new byte[1024];
            while (true)
            {
                try
                {
                    //客户端接受消息
                    int Length = ClientSocket.Receive(msgArr, 0, msgArr.Length, SocketFlags.None);
                    if (Length == 0)
                    {
                        ClientSocket.Close();
                        SocketPoolList.Remove(ClientSocket);
                        return;
                    }
                    string clientMsg =  Encoding.UTF8.GetString(msgArr, 0, Length);
                    Console.WriteLine("客户端发送的消息为:"+clientMsg);

                    byte[] msg = new byte[Length];
                    Array.Copy(msgArr, 0, msg,0, Length);
                    for (int i = 0; i < SocketPoolList.Count; i++)
                    {
                        if(SocketPoolList[i] == ClientSocket)
                        {
                            continue;
                        }
                        SocketPoolList[i].Send(msg);
                    }

                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    ClientSocket.Close();
                    SocketPoolList.Remove(ClientSocket);
                    return;
                }
            }
            
        }

    }
}

客户端3.0

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace ClientTestOne
{
    class Program
    {
        static Socket clientSocket;
        static void Main(string[] args)
        {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress iPAddress = IPAddress.Parse("192.168.117.1");
            int port = 8899;
            clientSocket.Connect(new IPEndPoint(iPAddress, port));
            Console.WriteLine("客户端开始连接服务器!");

            Console.WriteLine("请输入你的名字:");
            String name = Console.ReadLine();

            Thread thread = new Thread(ReceiveMsg);
            thread.Start();
     
            while (true)
            {
                string content = name + ":"+Console.ReadLine();
                byte[] msg = Encoding.UTF8.GetBytes(content);
                clientSocket.Send(msg);
            }

            Console.ReadKey();
        }

        static void ReceiveMsg()
        {
            byte[] MsgArr = new byte[1024];
            while (true)
            {
                int Length = clientSocket.Receive(MsgArr, 0, MsgArr.Length, SocketFlags.None);
                string msg = Encoding.UTF8.GetString(MsgArr, 0, Length);
                Console.WriteLine(msg);
            }
        }

    }
   
}

运行截图:

?四:改写成为异步服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace AsyncChatServer
{
    class Program
    {
        //消息的广播:需要使用List容器存储与客户端建立的连接
        private static List<Socket> SocketPoolList = new List<Socket>();
        static void Main(string[] args)
        {
            try
            {
                Socket Serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress iPAdress = IPAddress.Parse("192.168.117.1");
                int port = 8899;
                Serversocket.Bind(new IPEndPoint(iPAdress, port));
                Serversocket.Listen(10);

                Console.WriteLine("服务器启动了");
                
                Serversocket.BeginAccept(AsyncAccept,Serversocket);//开启异步接受客户端连接
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadKey();

        }

        static byte[] msgArr = new byte[1024]; 
        private static void AsyncAccept(IAsyncResult ar)
        {
            Socket serverSocket = ar.AsyncState as Socket;
            if (serverSocket == null)
            {
                return;
            }
            Socket clientSocket = serverSocket.EndAccept(ar);
            SocketPoolList.Add(clientSocket);

            clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReveive, clientSocket);

            serverSocket.BeginAccept(AsyncAccept, serverSocket);


        }

        private static void AsyncReveive(IAsyncResult ar)
        {
            Socket clientSocket = ar.AsyncState as Socket;
            try
            {
                int Length = clientSocket.EndReceive(ar);
                if (Length ==0)
                {
                    clientSocket.Close();
                    SocketPoolList.Remove(clientSocket);
                    return;
                }
                string message = Encoding.UTF8.GetString(msgArr,0,Length);
                Console.WriteLine(message);

               
                //消息的广播
                byte[] msg = new byte[Length];
                Array.Copy(msgArr, 0, msg, 0, Length);
                for (int i = 0; i < SocketPoolList.Count; i++)
                {
                    if (SocketPoolList[i] == clientSocket)
                    {
                        continue;
                    }
                    SocketPoolList[i].Send(msg);
                }

                //重新开启监听
                clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReveive, clientSocket);

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                clientSocket.Close();
                SocketPoolList.Remove(clientSocket);
                return;
            }
        }
    }
}

效果同上

思考:有没有问题呢?会不会出错呢?

不会出错,但是有问题,在服务器上的客户端连接接受消息间隔时间很短的情况下,那么就会导致向客户端广播的消息为同一条消息,因为连接上了服务器的客户端在接受消息的时候是异步的,而且共用堆中的数据byte[],因此在间隔时间很短的情况下,那么就会导致客户端接受的消息为同一条消息。

底层原理:多线程在执行的时候,会共享堆内存中的数据(不共享栈内存中的数据)

五、Client类的封装

解决四中的问题,可以利用面向对象的思想改进,将client连接封装成为一个类,使每一个client都能拥有自己byte[]数组来接受消息。

ClientPeer类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace AsyncChatServer
{
    class ClientPeer
    {
        Socket clientSocket = null;

        static byte[] msgArr = new byte[1024];

        internal ClientPeer(Socket clientSocket)
        {
            this.clientSocket = clientSocket;

            clientSocket.BeginReceive(msgArr,0,msgArr.Length, SocketFlags.None, AsyncReceive, clientSocket);
        }

        internal void AsyncReceive(IAsyncResult ar)
        {
            try
            {
                Socket clientSocket = ar.AsyncState as Socket;
                int length = clientSocket.EndReceive(ar);
                if (clientSocket == null)
                {
                    clientSocket.Close();
                    NetManager.Instance.RemoveClient(this);
                    return;
                }

                string message = Encoding.UTF8.GetString(msgArr,0,length);
                Console.WriteLine(message);

                NetManager.Instance.BoardCastMessage(message, this);

                clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive, clientSocket);
               
                
            }
            catch (Exception e)
            {
                clientSocket.Close();
                NetManager.Instance.RemoveClient(this);
                Console.WriteLine(e.Message);
                return;
            }
            
        }

        public void SendMessage(byte[] message)
        {
            clientSocket.Send(message);
        }

        public void SendMessage(string message)
        {
            clientSocket.Send(Encoding.UTF8.GetBytes(message));
        }
    }
}

NetManager类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace AsyncChatServer
{

    class NetManager
    {
        private static NetManager _instance = null;
        private NetManager()
        {

        }

        public static NetManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new NetManager();
                }
                return _instance;
            }
        }

        //消息的广播:需要使用List容器存储与客户端建立的连接
        private static List<ClientPeer> clientList = new List<ClientPeer>();

        public void AddClient(ClientPeer client)
        {
            clientList.Add(client);
        }

        public void RemoveClient(ClientPeer client)
        {
            clientList.Remove(client);
        }

        public void BoardCastMessage(string message,ClientPeer client = null)
        {
            for (int i = 0; i < clientList.Count; i++)
            {
                if (client!=null&& clientList[i] == client)
                {
                    continue;
                }
                clientList[i].SendMessage(message);
            }
        }
        public void BoardCastMessage(byte[] message, ClientPeer client = null)
        {
            for (int i = 0; i < clientList.Count; i++)
            {
                if (client != null && clientList[i] == client)
                {
                    continue;
                }
                clientList[i].SendMessage(message);
            }
        }

        public void SendMessage(byte[] message,ClientPeer client)
        {
            client.SendMessage(message);
        }

        public void SendMessage(string message, ClientPeer client)
        {
            client.SendMessage(message);
        }

    }
}

main函数类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace AsyncChatServer
{
    class Program
    {
       
        static void Main(string[] args)
        {
            try
            {
                Socket Serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress iPAdress = IPAddress.Parse("192.168.117.1");
                int port = 8899;
                Serversocket.Bind(new IPEndPoint(iPAdress, port));
                Serversocket.Listen(10);

                Console.WriteLine("服务器启动了");
                
                Serversocket.BeginAccept(AsyncAccept, Serversocket);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadKey();

        }

        static byte[] msgarr = new byte[1024];

        private static void AsyncAccept(IAsyncResult ar)
        {
            Socket serversocket = ar.AsyncState as Socket;
            if (serversocket == null)
            {
                return;
            }
            Socket clientsocket = serversocket.EndAccept(ar);

            ClientPeer clientPeer = new ClientPeer(clientsocket);
            NetManager.Instance.AddClient(clientPeer);

            //clientsocket.beginreceive(msgarr, 0, msgarr.length, socketflags.none, asyncreveive, clientsocket);

            serversocket.BeginAccept(AsyncAccept, serversocket);


        }
    }
}

按理来说:ip端口应该也不应该放在Main函数中,

六、动态链接库:

ddl:包含该动态链接库实际的函数和数据。在程序运行阶段,加载该文件,并将该文件映射到进程地址空间中,然后访问该文件中的相应函数。

一般用来实现一些工具类,配置接口

生成.dll文件

七、将网络模块移植到unity中:

代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

public class NetManager : MonoBehaviour
{
    //单例
    private static NetManager _instance = null;

    private NetManager()
    {
        
    }

    private static NetManager Instance
    {
        get
        {
            if(_instance == null)
            {
                _instance = new NetManager();
            }
            return _instance;
        }
    }
    // Start is called before the first frame update
    //客户端连接服务器
    //1.连接到服务器
    //2.接受服务器的消息,并处理
    //3.向服务器发送消息
    byte[] msgArr = new byte[1024];
    Socket clientSocket = null;
    
    //消息队列,用于处理消息
    Queue<string> messageQueue = new Queue<string>();

    private void OnEnable()
    {
        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    }
    

    void Start()
    {
        
        clientSocket.Connect(new IPEndPoint(IPAddress.Parse(Protocol.ProtocolConfig.ip), Protocol.ProtocolConfig.port));
        Debug.Log("客户端开始连接服务器!");
        try
        {
            clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive, clientSocket);
        }
        catch (System.Exception e)
        {
            Debug.Log(e.Message);
            
        }

    }

    //接受服务器的消息
    private void AsyncReceive(IAsyncResult ar)
    {
        Socket clientSocket = ar.AsyncState as Socket;
        if (clientSocket == null)
        {
            return;
        }
        int length = clientSocket.EndReceive(ar);
        string message = Encoding.UTF8.GetString(msgArr, 0, length);//接受的消息,思考为啥不在这个函数里面处理消息
                                                                    //异步的本质是一条多线程,很多Unity的API没有办法在支线程中使用
        messageQueue.Enqueue(message);

        clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive, clientSocket);

        
    }

    private void SendMessageToServer(string message)
    {
        clientSocket.Send(Encoding.UTF8.GetBytes(message));
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            SendMessageToServer("helloWorld");
        }

        if (messageQueue.Count>0)
        {
            string message = messageQueue.Dequeue();
            //处理这个消息
            Debug.Log(message);
        }
    }
}

运行成功:

?思考:接受的消息为啥不在异步函数中执行?为啥要用到消息队列

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:31:34  更:2022-10-31 12:32:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/17 6:13:33-

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