0

0

C#高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)

黄舟

黄舟

发布时间:2017-02-27 10:59:39

|

4655人浏览过

|

来源于php中文网

原创

原创性申明

本文作者:小竹zz  博客地址:http://www.php.cn/转载请注明出处

引言

我一直在探寻一个高性能的Socket客户端代码。以前,我使用Socket类写了一些基于传统异步编程模型的代码(BeginSend、BeginReceive,等等)也看过很多博客的知识,在linux中有poll和epoll来实现,在windows下面
微软MSDN中也提供了SocketAsyncEventArgs这个类来实现IOCP 地址:http://www.php.cn/
NET Framework中的APM也称为Begin/End模式。这是因为会调用Begin方法来启动异步操作,然后返回一个IAsyncResult 对象。可以选择将一个代理作为参数提供给Begin方法,异步操作完成时会调用该方法。或者,一个线程可以等待 IAsyncResult.AsyncWaitHandle。当回调被调用或发出等待信号时,就会调用End方法来获取异步操作的结果。这种模式很灵活,使用相对简单,在 .NET Framework 中非常常见。
但是,您必须注意,如果进行大量异步套接字操作,是要付出代价的。针对每次操作,都必须创建一个IAsyncResult对象,而且该对象不能被重复使用。由于大量使用对象分配和垃圾收集,这会影响性能。为了解决这个问题,新版本提供了另一个使用套接字上执行异步I/O的方法模式。这种新模式并不要求为每个套接字操作分配操作上下文对象。

代码下载:http://www.php.cn/ 这里的代码优化了的

目标

在上面微软提供的例子我觉得不是很完整,没有具体一个流程,只是受到客户端消息后发送相同内容给客户端,初学者不容易看懂流程,因为我花了一天的时间来实现一个功能齐全的IOCP服务器,

效果如下


代码

首先是ICOPServer.cs 这个类是IOCP服务器的核心类,目前这个类是网络上比较全的代码,MSDN上面的例子都没有我的全

黄城网络办公系统
黄城网络办公系统

具有功能全面实用、安全性稳定性高、易操作、管理维护简单的特点,采用独创的智能型技术,web服务器、数据库和应用程序全部自动傻瓜安装配置,用户可在一分钟内自行安装完毕,无需专业人员即可自行维护,B/S结构,适用于Intranet/Internet应用,客户端只需浏览器便可连接办公系统,无论出差旅行,还是居家办公,工作都能得心应手,实现无地域限制的全球办公,具有邮件管理、业务管理、网络硬盘、智能工作流

下载
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace ServerTest
{
    /// 
    /// IOCP SOCKET服务器
    /// 
    public class IOCPServer : IDisposable
    {
        const int opsToPreAlloc = 2;
        #region Fields
        /// 
        /// 服务器程序允许的最大客户端连接数
        /// 
        private int _maxClient;

        /// 
        /// 监听Socket,用于接受客户端的连接请求
        /// 
        private Socket _serverSock;

        /// 
        /// 当前的连接的客户端数
        /// 
        private int _clientCount;

        /// 
        /// 用于每个I/O Socket操作的缓冲区大小
        /// 
        private int _bufferSize = 1024;

        /// 
        /// 信号量
        /// 
        Semaphore _maxAcceptedClients;

        /// 
        /// 缓冲区管理
        /// 
        BufferManager _bufferManager;

        /// 
        /// 对象池
        /// 
        SocketAsyncEventArgsPool _objectPool;

        private bool disposed = false;

        #endregion

        #region Properties

        /// 
        /// 服务器是否正在运行
        /// 
        public bool IsRunning { get; private set; }
        /// 
        /// 监听的IP地址
        /// 
        public IPAddress Address { get; private set; }
        /// 
        /// 监听的端口
        /// 
        public int Port { get; private set; }
        /// 
        /// 通信使用的编码
        /// 
        public Encoding Encoding { get; set; }

        #endregion

        #region Ctors

        /// 
        /// 异步IOCP SOCKET服务器
        /// 
        /// 监听的端口
        /// 最大的客户端数量
        public IOCPServer(int listenPort,int maxClient)
            : this(IPAddress.Any, listenPort, maxClient)
        {
        }

        /// 
        /// 异步Socket TCP服务器
        /// 
        /// 监听的终结点
        /// 最大客户端数量
        public IOCPServer(IPEndPoint localEP, int maxClient)
            : this(localEP.Address, localEP.Port,maxClient)
        {
        }

        /// 
        /// 异步Socket TCP服务器
        /// 
        /// 监听的IP地址
        /// 监听的端口
        /// 最大客户端数量
        public IOCPServer(IPAddress localIPAddress, int listenPort, int maxClient)
        {
            this.Address = localIPAddress;
            this.Port = listenPort;
            this.Encoding = Encoding.Default;

            _maxClient = maxClient;

            _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            _bufferManager = new BufferManager(_bufferSize * _maxClient * opsToPreAlloc,_bufferSize);

            _objectPool = new SocketAsyncEventArgsPool(_maxClient);

            _maxAcceptedClients = new Semaphore(_maxClient, _maxClient); 
        }

        #endregion


        #region 初始化

        /// 
        /// 初始化函数
        /// 
        public void Init()
        {
            // Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds 
            // against memory fragmentation
            _bufferManager.InitBuffer();

            // preallocate pool of SocketAsyncEventArgs objects
            SocketAsyncEventArgs readWriteEventArg;

            for (int i = 0; i < _maxClient; i++)
            {
                //Pre-allocate a set of reusable SocketAsyncEventArgs
                readWriteEventArg = new SocketAsyncEventArgs();
                readWriteEventArg.Completed += new EventHandler(OnIOCompleted);
                readWriteEventArg.UserToken = null;

                // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object
                _bufferManager.SetBuffer(readWriteEventArg);

                // add SocketAsyncEventArg to the pool
                _objectPool.Push(readWriteEventArg);
            }

        }

        #endregion

        #region Start
        /// 
        /// 启动
        /// 
        public void Start()
        {
            if (!IsRunning)
            {
                Init();
                IsRunning = true;
                IPEndPoint localEndPoint = new IPEndPoint(Address, Port);
                // 创建监听socket
                _serverSock = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                //_serverSock.ReceiveBufferSize = _bufferSize;
                //_serverSock.SendBufferSize = _bufferSize;
                if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    // 配置监听socket为 dual-mode (IPv4 & IPv6) 
                    // 27 is equivalent to IPV6_V6ONLY socket option in the winsock snippet below,
                    _serverSock.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
                    _serverSock.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
                }
                else
                {
                    _serverSock.Bind(localEndPoint);
                }
                // 开始监听
                _serverSock.Listen(this._maxClient);
                // 在监听Socket上投递一个接受请求。
                StartAccept(null);
            }
        }
        #endregion

        #region Stop

        /// 
        /// 停止服务
        /// 
        public void Stop()
        {
            if (IsRunning)
            {
                IsRunning = false;
                _serverSock.Close();
                //TODO 关闭对所有客户端的连接

            }
        }

        #endregion


        #region Accept

        /// 
        /// 从客户端开始接受一个连接操作
        /// 
        private void StartAccept(SocketAsyncEventArgs asyniar)
        {
            if (asyniar == null)
            {
                asyniar = new SocketAsyncEventArgs();
                asyniar.Completed += new EventHandler(OnAcceptCompleted);
            }
            else
            {
                //socket must be cleared since the context object is being reused
                asyniar.AcceptSocket = null;
            }
            _maxAcceptedClients.WaitOne();
            if (!_serverSock.AcceptAsync(asyniar))
            {
                ProcessAccept(asyniar);
                //如果I/O挂起等待异步则触发AcceptAsyn_Asyn_Completed事件
                //此时I/O操作同步完成,不会触发Asyn_Completed事件,所以指定BeginAccept()方法
            }
        }

        /// 
        /// accept 操作完成时回调函数
        /// 
        /// Object who raised the event.
        /// SocketAsyncEventArg associated with the completed accept operation.
        private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept(e);
        }

        /// 
        /// 监听Socket接受处理
        /// 
        /// SocketAsyncEventArg associated with the completed accept operation.
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                Socket s = e.AcceptSocket;//和客户端关联的socket
                if (s.Connected)
                {
                    try
                    {
                        
                        Interlocked.Increment(ref _clientCount);//原子操作加1
                        SocketAsyncEventArgs asyniar = _objectPool.Pop();
                        asyniar.UserToken = s;

                        Log4Debug(String.Format("客户 {0} 连入, 共有 {1} 个连接。", s.RemoteEndPoint.ToString(), _clientCount));
                        
                        if (!s.ReceiveAsync(asyniar))//投递接收请求
                        {
                            ProcessReceive(asyniar);
                        }
                    }
                    catch (SocketException ex)
                    {
                        Log4Debug(String.Format("接收客户 {0} 数据出错, 异常信息: {1} 。", s.RemoteEndPoint, ex.ToString()));
                        //TODO 异常处理
                    }
                    //投递下一个接受请求
                    StartAccept(e);
                }
            }
        }

        #endregion

        #region 发送数据

        /// 
        /// 异步的发送数据
        /// 
        /// 
        /// 
        public void Send(SocketAsyncEventArgs e, byte[] data)
        {
            if (e.SocketError == SocketError.Success)
            {
                Socket s = e.AcceptSocket;//和客户端关联的socket
                if (s.Connected)
                {
                    Array.Copy(data, 0, e.Buffer, 0, data.Length);//设置发送数据

                    //e.SetBuffer(data, 0, data.Length); //设置发送数据
                    if (!s.SendAsync(e))//投递发送请求,这个函数有可能同步发送出去,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件
                    {
                        // 同步发送时处理发送完成事件
                        ProcessSend(e);
                    }
                    else
                    {
                        CloseClientSocket(e);
                    }
                }
            }
        }

        /// 
        /// 同步的使用socket发送数据
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public void Send(Socket socket, byte[] buffer, int offset, int size, int timeout)
        {
            socket.SendTimeout = 0;
            int startTickCount = Environment.TickCount;
            int sent = 0; // how many bytes is already sent
            do
            {
                if (Environment.TickCount > startTickCount + timeout)
                {
                    //throw new Exception("Timeout.");
                }
                try
                {
                    sent += socket.Send(buffer, offset + sent, size - sent, SocketFlags.None);
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.WouldBlock ||
                    ex.SocketErrorCode == SocketError.IOPending ||
                    ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
                    {
                        // socket buffer is probably full, wait and try again
                        Thread.Sleep(30);
                    }
                    else
                    {
                        throw ex; // any serious error occurr
                    }
                }
            } while (sent < size);
        }


        /// 
        /// 发送完成时处理函数
        /// 
        /// 与发送完成操作相关联的SocketAsyncEventArg对象
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                Socket s = (Socket)e.UserToken;

                //TODO
            }
            else
            {
                CloseClientSocket(e);
            }
        }

        #endregion

        #region 接收数据


        /// 
        ///接收完成时处理函数
        /// 
        /// 与接收完成操作相关联的SocketAsyncEventArg对象
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)//if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                // 检查远程主机是否关闭连接
                if (e.BytesTransferred > 0)
                {
                    Socket s = (Socket)e.UserToken;
                    //判断所有需接收的数据是否已经完成
                    if (s.Available == 0)
                    {
                        //从侦听者获取接收到的消息。 
                        //String received = Encoding.ASCII.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                        //echo the data received back to the client
                        //e.SetBuffer(e.Offset, e.BytesTransferred);

                        byte[] data = new byte[e.BytesTransferred];
                        Array.Copy(e.Buffer, e.Offset, data, 0, data.Length);//从e.Buffer块中复制数据出来,保证它可重用

                        string info=Encoding.Default.GetString(data);
                        Log4Debug(String.Format("收到 {0} 数据为 {1}",s.RemoteEndPoint.ToString(),info));
                        //TODO 处理数据

                        //增加服务器接收的总字节数。
                    }

                    if (!s.ReceiveAsync(e))//为接收下一段数据,投递接收请求,这个函数有可能同步完成,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件
                    {
                        //同步接收时处理接收完成事件
                        ProcessReceive(e);
                    }
                }
            }
            else
            {
                CloseClientSocket(e);
            }
        }

        #endregion

        #region 回调函数

        /// 
        /// 当Socket上的发送或接收请求被完成时,调用此函数
        /// 
        /// 激发事件的对象
        /// 与发送或接收完成操作相关联的SocketAsyncEventArg对象
        private void OnIOCompleted(object sender, SocketAsyncEventArgs e)
        {
            // Determine which type of operation just completed and call the associated handler.
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Accept:
                    ProcessAccept(e);
                    break;
                case SocketAsyncOperation.Receive:
                    ProcessReceive(e);
                    break;
                default:
                    throw new ArgumentException("The last operation completed on the socket was not a receive or send");
            }
        }

        #endregion

        #region Close
        /// 
        /// 关闭socket连接
        /// 
        /// SocketAsyncEventArg associated with the completed send/receive operation.
        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            Log4Debug(String.Format("客户 {0} 断开连接!",((Socket)e.UserToken).RemoteEndPoint.ToString()));
            Socket s = e.UserToken as Socket;
            CloseClientSocket(s, e);
        }

        /// 
        /// 关闭socket连接
        /// 
        /// 
        /// 
        private void CloseClientSocket(Socket s, SocketAsyncEventArgs e)
        {
            try
            {
                s.Shutdown(SocketShutdown.Send);
            }
            catch (Exception)
            {
                // Throw if client has closed, so it is not necessary to catch.
            }
            finally
            {
                s.Close();
            }
            Interlocked.Decrement(ref _clientCount);
            _maxAcceptedClients.Release();
            _objectPool.Push(e);//SocketAsyncEventArg 对象被释放,压入可重用队列。
        }
        #endregion

        #region Dispose
        /// 
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// 
        /// Releases unmanaged and - optionally - managed resources
        /// 
        /// true to release 
        /// both managed and unmanaged resources; false 
        /// to release only unmanaged resources.
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    try
                    {
                        Stop();
                        if (_serverSock != null)
                        {
                            _serverSock = null;
                        }
                    }
                    catch (SocketException ex)
                    {
                        //TODO 事件
                    }
                }
                disposed = true;
            }
        }
        #endregion

        public void Log4Debug(string msg)
        {
            Console.WriteLine("notice:"+msg);
        }

    }
}


BufferManager.cs 这个类是缓存管理类,是采用MSDN上面的例子一样的 地址: http://www.php.cn/

SocketAsyncEventArgsPool.cs 这个类也是来自MSDN的 地址:http://www.php.cn/

需要的话自己到MSDN网站上去取,我就不贴出来了

服务器端

static void Main(string[] args)
        {

            IOCPServer server = new IOCPServer(8088, 1024);
            server.Start();
            Console.WriteLine("服务器已启动....");
            System.Console.ReadLine();
        }

客户端

客户端代码也是很简单

static void Main(string[] args)
        {
            IPAddress remote=IPAddress.Parse("192.168.3.4");
            client c = new client(8088,remote);

            c.connect();
            Console.WriteLine("服务器连接成功!");
            while (true)
            {
                Console.Write("send>");
                string msg=Console.ReadLine();
                if (msg == "exit")
                    break;
                c.send(msg);
            }
            c.disconnect();
            Console.ReadLine();
        }

client.cs

public class client
    {

        public TcpClient _client;

        public int port;

        public IPAddress remote;

        public client(int port,IPAddress remote)
        {

            this.port = port;
            this.remote = remote;
        }

        public void connect()
        {
            this._client=new TcpClient();
            _client.Connect(remote, port);
        }
        public void disconnect()
        {
            _client.Close();
        }
        public void send(string msg)
        {
            byte[] data=Encoding.Default.GetBytes(msg);
            _client.GetStream().Write(data, 0, data.Length);
        }
    }


IOCPClient类,使用SocketAsyncEventArgs类建立一个Socket客户端。虽然MSDN说这个类特别设计给网络服务器应用,但也没有限制在客户端代码中使用APM。下面给出了IOCPClient类的样例代码:

 public class IOCPClient
    {
        /// 
        /// 连接服务器的socket
        /// 
        private Socket _clientSock;

        /// 
        /// 用于服务器执行的互斥同步对象
        /// 
        private static Mutex mutex = new Mutex();
        /// 
        /// Socket连接标志
        /// 
        private Boolean _connected = false;

        private const int ReceiveOperation = 1, SendOperation = 0;

        private static AutoResetEvent[]
                 autoSendReceiveEvents = new AutoResetEvent[]
         {
             new AutoResetEvent(false),
             new AutoResetEvent(false)
         };

        /// 
        /// 服务器监听端点
        /// 
        private IPEndPoint _remoteEndPoint;

        public IOCPClient(IPEndPoint local,IPEndPoint remote)
        {
            _clientSock = new Socket(local.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
            _remoteEndPoint = remote;
        }

        #region 连接服务器

        /// 
        /// 连接远程服务器
        /// 
        public void Connect()
        {
            SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();

            connectArgs.UserToken = _clientSock;
            connectArgs.RemoteEndPoint = _remoteEndPoint;
            connectArgs.Completed += new EventHandler(OnConnected);
            mutex.WaitOne();
            if (!_clientSock.ConnectAsync(connectArgs))//异步连接
            {
                ProcessConnected(connectArgs);
            }
            
        }
        /// 
        /// 连接上的事件
        /// 
        /// 
        /// 
        void OnConnected(object sender, SocketAsyncEventArgs e)
        {
            mutex.ReleaseMutex();
            //设置Socket已连接标志。 
            _connected = (e.SocketError == SocketError.Success);
        }
        /// 
        /// 处理连接服务器
        /// 
        /// 
        private void ProcessConnected(SocketAsyncEventArgs e)
        {
            //TODO
        }

        #endregion

        #region 发送消息
        /// 
        /// 向服务器发送消息
        /// 
        /// 
        public void Send(byte[] data)
        {
            SocketAsyncEventArgs asyniar = new SocketAsyncEventArgs();
            asyniar.Completed += new EventHandler(OnSendComplete);
            asyniar.SetBuffer(data, 0, data.Length);
            asyniar.UserToken = _clientSock;
            asyniar.RemoteEndPoint = _remoteEndPoint;
            autoSendReceiveEvents[SendOperation].WaitOne();
            if (!_clientSock.SendAsync(asyniar))//投递发送请求,这个函数有可能同步发送出去,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件
            {
                // 同步发送时处理发送完成事件
                ProcessSend(asyniar);
            }
        }

        /// 
        /// 发送操作的回调方法
        /// 
        /// 
        /// 
        private void OnSendComplete(object sender, SocketAsyncEventArgs e)
        {
            //发出发送完成信号。 
            autoSendReceiveEvents[SendOperation].Set();
            ProcessSend(e);
        }

        /// 
        /// 发送完成时处理函数
        /// 
        /// 与发送完成操作相关联的SocketAsyncEventArg对象
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            //TODO
        }
        #endregion

        #region 接收消息
        /// 
        /// 开始监听服务端数据
        /// 
        /// 
        public void StartRecive(SocketAsyncEventArgs e)
        {
            //准备接收。 
            Socket s = e.UserToken as Socket;
            byte[] receiveBuffer = new byte[255];
            e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
            e.Completed += new EventHandler(OnReceiveComplete);
            autoSendReceiveEvents[ReceiveOperation].WaitOne();
            if (!s.ReceiveAsync(e))
            {
                ProcessReceive(e);
            }
        }

        /// 
        /// 接收操作的回调方法
        /// 
        /// 
        /// 
        private void OnReceiveComplete(object sender, SocketAsyncEventArgs e)
        {
            //发出接收完成信号。 
            autoSendReceiveEvents[ReceiveOperation].Set();
            ProcessReceive(e);
        }

        /// 
        ///接收完成时处理函数
        /// 
        /// 与接收完成操作相关联的SocketAsyncEventArg对象
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                // 检查远程主机是否关闭连接
                if (e.BytesTransferred > 0)
                {
                    Socket s = (Socket)e.UserToken;
                    //判断所有需接收的数据是否已经完成
                    if (s.Available == 0)
                    {
                        byte[] data = new byte[e.BytesTransferred];
                        Array.Copy(e.Buffer, e.Offset, data, 0, data.Length);//从e.Buffer块中复制数据出来,保证它可重用

                        //TODO 处理数据
                    }

                    if (!s.ReceiveAsync(e))//为接收下一段数据,投递接收请求,这个函数有可能同步完成,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件
                    {
                        //同步接收时处理接收完成事件
                        ProcessReceive(e);
                    }
                }
            }
        }

        #endregion


        public void Close()
        {
            _clientSock.Disconnect(false);
        }

        /// 
        /// 失败时关闭Socket,根据SocketError抛出异常。
        /// 
        /// 
 
        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s.Connected)
            {
                //关闭与客户端关联的Socket
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    //如果客户端处理已经关闭,抛出异常 
                }
                finally
                {
                    if (s.Connected)
                    {
                        s.Close();
                    }
                }
            }
            //抛出SocketException 
            throw new SocketException((Int32)e.SocketError);
        }


        /// 
        /// 释放SocketClient实例
        /// 
        public void Dispose()
        {
            mutex.Close();
            autoSendReceiveEvents[SendOperation].Close();
            autoSendReceiveEvents[ReceiveOperation].Close();
            if (_clientSock.Connected)
            {
                _clientSock.Close();
            }
        }

    }

这个类我没有测试,但是理论上是没问题的。

 以上就是C#,SocketAsyncEventArgs,服务器的内容,更多相关内容请关注PHP中文网(www.php.cn)!

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

c#

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

8

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

6

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

1

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

17

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

18

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.9万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

C++教程
C++教程

共115课时 | 14.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号