C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

本文主要是介绍C#网络编程系列文章(三)之TcpListener实现异步TCP服务器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原创性声明

本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处

文章系列目录

C#网络编程系列文章(一)之Socket实现异步TCP服务器 

C#网络编程系列文章(二)之Socket实现同步TCP服务器

C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

C#网络编程系列文章(五)之Socket实现异步UDP服务器

C#网络编程系列文章(六)之Socket实现同步UDP服务器

C#网络编程系列文章(七)之UdpClient实现异步UDP服务器

C#网络编程系列文章(八)之UdpClient实现同步UDP服务器


本文介绍

TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。 可使用 TcpClient 或 Socket 来连接 TcpListener。 可使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener。 可以将本地 IP 地址指定为 Any,将本地端口号指定为 0(如果希望基础服务提供程序为您分配这些值)。 如果您选择这样做,可在连接套接字后使用 LocalEndpoint 属性来标识已指定的信息。使用 Start 方法,可开始侦听传入的连接请求。 Start 将对传入连接进行排队,直至您调用 Stop 方法或它已经完成 MaxConnections 排队为止。 可使用 AcceptSocket 或 AcceptTcpClient 从传入连接请求队列提取连接。 这两种方法将阻止。 如果要避免阻止,可首先使用 Pending 方法来确定队列中是否有可用的连接请求。

虽然TcpListener已经封装的比较不错了,我们于是就使用它在构造一个比较不错的异步TCP服务器,这里依然和前两章一样,给出服务器中的代码,代码中注释很详细,我也会给出相关的封装类。

TcpListener异步TCP服务器

服务器代码
[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6. using System.Net;  
  7. namespace NetFrame.Net.TCP.Listener.Asynchronous  
  8. {  
  9.     /// <summary>  
  10.     /// TcpListener实现异步TCP服务器  
  11.     /// </summary>  
  12.     public class AsyncTCPServer : IDisposable  
  13.     {  
  14.         #region Fields  
  15.         /// <summary>  
  16.         /// 服务器程序允许的最大客户端连接数  
  17.         /// </summary>  
  18.         private int _maxClient;  
  19.   
  20.         /// <summary>  
  21.         /// 当前的连接的客户端数  
  22.         /// </summary>  
  23.         private int _clientCount;  
  24.   
  25.         /// <summary>  
  26.         /// 服务器使用的异步TcpListener  
  27.         /// </summary>  
  28.         private TcpListener _listener;  
  29.   
  30.         /// <summary>  
  31.         /// 客户端会话列表  
  32.         /// </summary>  
  33.         private List<Object> _clients;  
  34.   
  35.         private bool disposed = false;  
  36.  
  37.         #endregion  
  38.  
  39.         #region Properties  
  40.   
  41.         /// <summary>  
  42.         /// 服务器是否正在运行  
  43.         /// </summary>  
  44.         public bool IsRunning { getprivate set; }  
  45.         /// <summary>  
  46.         /// 监听的IP地址  
  47.         /// </summary>  
  48.         public IPAddress Address { getprivate set; }  
  49.         /// <summary>  
  50.         /// 监听的端口  
  51.         /// </summary>  
  52.         public int Port { getprivate set; }  
  53.         /// <summary>  
  54.         /// 通信使用的编码  
  55.         /// </summary>  
  56.         public Encoding Encoding { getset; }  
  57.  
  58.  
  59.         #endregion  
  60.  
  61.         #region 构造函数  
  62.   
  63.         /// <summary>  
  64.         /// 异步TCP服务器  
  65.         /// </summary>  
  66.         /// <param name="listenPort">监听的端口</param>  
  67.         public AsyncTCPServer(int listenPort)  
  68.             : this(IPAddress.Any, listenPort)  
  69.         {  
  70.         }  
  71.   
  72.         /// <summary>  
  73.         /// 异步TCP服务器  
  74.         /// </summary>  
  75.         /// <param name="localEP">监听的终结点</param>  
  76.         public AsyncTCPServer(IPEndPoint localEP)  
  77.             : this(localEP.Address, localEP.Port)  
  78.         {  
  79.         }  
  80.   
  81.         /// <summary>  
  82.         /// 异步TCP服务器  
  83.         /// </summary>  
  84.         /// <param name="localIPAddress">监听的IP地址</param>  
  85.         /// <param name="listenPort">监听的端口</param>  
  86.         public AsyncTCPServer(IPAddress localIPAddress, int listenPort)  
  87.         {  
  88.             Address = localIPAddress;  
  89.             Port = listenPort;  
  90.             this.Encoding = Encoding.Default;  
  91.   
  92.             _clients = new List<Object>();  
  93.   
  94.             _listener = new TcpListener(Address, Port);  
  95.             _listener.AllowNatTraversal(true);  
  96.         }  
  97.  
  98.         #endregion  
  99.  
  100.         #region Method  
  101.   
  102.         /// <summary>  
  103.         /// 启动服务器  
  104.         /// </summary>  
  105.         public void Start()  
  106.         {  
  107.             if (!IsRunning)  
  108.             {  
  109.                 IsRunning = true;  
  110.                 _listener.Start();  
  111.                 _listener.BeginAcceptTcpClient(  
  112.                   new AsyncCallback(HandleTcpClientAccepted), _listener);  
  113.             }  
  114.         }  
  115.   
  116.   
  117.         /// <summary>  
  118.         /// 启动服务器  
  119.         /// </summary>  
  120.         /// <param name="backlog">  
  121.         /// 服务器所允许的挂起连接序列的最大长度  
  122.         /// </param>  
  123.         public void Start(int backlog)  
  124.         {  
  125.             if (!IsRunning)  
  126.             {  
  127.                 IsRunning = true;  
  128.                 _listener.Start(backlog);  
  129.                 _listener.BeginAcceptTcpClient(  
  130.                   new AsyncCallback(HandleTcpClientAccepted), _listener);  
  131.             }  
  132.         }  
  133.   
  134.         /// <summary>  
  135.         /// 停止服务器  
  136.         /// </summary>  
  137.         public void Stop()  
  138.         {  
  139.             if (IsRunning)  
  140.             {  
  141.                 IsRunning = false;  
  142.                 _listener.Stop();  
  143.                 lock (_clients)  
  144.                 {  
  145.                     //关闭所有客户端连接  
  146.                     CloseAllClient();  
  147.                 }  
  148.             }  
  149.         }  
  150.   
  151.         /// <summary>  
  152.         /// 处理客户端连接的函数  
  153.         /// </summary>  
  154.         /// <param name="ar"></param>  
  155.         private void HandleTcpClientAccepted(IAsyncResult ar)  
  156.         {  
  157.             if (IsRunning)  
  158.             {  
  159.                 //TcpListener tcpListener = (TcpListener)ar.AsyncState;  
  160.   
  161.                 TcpClient client = _listener.EndAcceptTcpClient(ar);  
  162.                 byte[] buffer = new byte[client.ReceiveBufferSize];  
  163.   
  164.                 TCPClientState state  
  165.                   = new TCPClientState(client, buffer);  
  166.                 lock (_clients)  
  167.                 {  
  168.                     _clients.Add(state);  
  169.                     RaiseClientConnected(state);  
  170.                 }  
  171.   
  172.                 NetworkStream stream = state.NetworkStream;  
  173.                 //开始异步读取数据  
  174.                 stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);  
  175.   
  176.                 _listener.BeginAcceptTcpClient(  
  177.                   new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);  
  178.             }  
  179.         }  
  180.         /// <summary>  
  181.         /// 数据接受回调函数  
  182.         /// </summary>  
  183.         /// <param name="ar"></param>  
  184.         private void HandleDataReceived(IAsyncResult ar)  
  185.         {  
  186.             if (IsRunning)  
  187.             {  
  188.                 TCPClientState state = (TCPClientState)ar.AsyncState;  
  189.                 NetworkStream stream = state.NetworkStream;  
  190.   
  191.                 int recv = 0;  
  192.                 try  
  193.                 {  
  194.                     recv = stream.EndRead(ar);  
  195.                 }  
  196.                 catch  
  197.                 {  
  198.                     recv = 0;  
  199.                 }  
  200.   
  201.                 if (recv == 0)  
  202.                 {  
  203.                     // connection has been closed  
  204.                     lock (_clients)  
  205.                     {  
  206.                         _clients.Remove(state);  
  207.                         //触发客户端连接断开事件  
  208.                         RaiseClientDisconnected(state);  
  209.                         return;  
  210.                     }  
  211.                 }  
  212.   
  213.                 // received byte and trigger event notification  
  214.                 byte[] buff = new byte[recv];  
  215.                 Buffer.BlockCopy(state.Buffer, 0, buff, 0, recv);  
  216.                 //触发数据收到事件  
  217.                 RaiseDataReceived(state);  
  218.   
  219.                 // continue listening for tcp datagram packets  
  220.                 stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);  
  221.             }  
  222.         }  
  223.   
  224.         /// <summary>  
  225.         /// 发送数据  
  226.         /// </summary>  
  227.         /// <param name="state">接收数据的客户端会话</param>  
  228.         /// <param name="data">数据报文</param>  
  229.         public void Send(TCPClientState state, byte[] data)  
  230.         {  
  231.             RaisePrepareSend(state);  
  232.             Send(state.TcpClient, data);  
  233.         }  
  234.   
  235.         /// <summary>  
  236.         /// 异步发送数据至指定的客户端  
  237.         /// </summary>  
  238.         /// <param name="client">客户端</param>  
  239.         /// <param name="data">报文</param>  
  240.         public void Send(TcpClient client, byte[] data)  
  241.         {  
  242.             if (!IsRunning)  
  243.                 throw new InvalidProgramException("This TCP Scoket server has not been started.");  
  244.   
  245.             if (client == null)  
  246.                 throw new ArgumentNullException("client");  
  247.   
  248.             if (data == null)  
  249.                 throw new ArgumentNullException("data");  
  250.             client.GetStream().BeginWrite(data, 0, data.Length, SendDataEnd, client);  
  251.         }  
  252.   
  253.         /// <summary>  
  254.         /// 发送数据完成处理函数  
  255.         /// </summary>  
  256.         /// <param name="ar">目标客户端Socket</param>  
  257.         private void SendDataEnd(IAsyncResult ar)  
  258.         {  
  259.             ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);  
  260.             RaiseCompletedSend(null);  
  261.         }  
  262.         #endregion  
  263.  
  264.         #region 事件  
  265.   
  266.         /// <summary>  
  267.         /// 与客户端的连接已建立事件  
  268.         /// </summary>  
  269.         public event EventHandler<AsyncEventArgs> ClientConnected;  
  270.         /// <summary>  
  271.         /// 与客户端的连接已断开事件  
  272.         /// </summary>  
  273.         public event EventHandler<AsyncEventArgs> ClientDisconnected;  
  274.   
  275.   
  276.         /// <summary>  
  277.         /// 触发客户端连接事件  
  278.         /// </summary>  
  279.         /// <param name="state"></param>  
  280.         private void RaiseClientConnected(TCPClientState state)  
  281.         {  
  282.             if (ClientConnected != null)  
  283.             {  
  284.                 ClientConnected(thisnew AsyncEventArgs(state));  
  285.             }  
  286.         }  
  287.         /// <summary>  
  288.         /// 触发客户端连接断开事件  
  289.         /// </summary>  
  290.         /// <param name="client"></param>  
  291.         private void RaiseClientDisconnected(TCPClientState state)  
  292.         {  
  293.             if (ClientDisconnected != null)  
  294.             {  
  295.                 ClientDisconnected(thisnew AsyncEventArgs("连接断开"));  
  296.             }  
  297.         }  
  298.   
  299.         /// <summary>  
  300.         /// 接收到数据事件  
  301.         /// </summary>  
  302.         public event EventHandler<AsyncEventArgs> DataReceived;  
  303.   
  304.         private void RaiseDataReceived(TCPClientState state)  
  305.         {  
  306.             if (DataReceived != null)  
  307.             {  
  308.                 DataReceived(thisnew AsyncEventArgs(state));  
  309.             }  
  310.         }  
  311.   
  312.         /// <summary>  
  313.         /// 发送数据前的事件  
  314.         /// </summary>  
  315.         public event EventHandler<AsyncEventArgs> PrepareSend;  
  316.   
  317.         /// <summary>  
  318.         /// 触发发送数据前的事件  
  319.         /// </summary>  
  320.         /// <param name="state"></param>  
  321.         private void RaisePrepareSend(TCPClientState state)  
  322.         {  
  323.             if (PrepareSend != null)  
  324.             {  
  325.                 PrepareSend(thisnew AsyncEventArgs(state));  
  326.             }  
  327.         }  
  328.   
  329.         /// <summary>  
  330.         /// 数据发送完毕事件  
  331.         /// </summary>  
  332.         public event EventHandler<AsyncEventArgs> CompletedSend;  
  333.   
  334.         /// <summary>  
  335.         /// 触发数据发送完毕的事件  
  336.         /// </summary>  
  337.         /// <param name="state"></param>  
  338.         private void RaiseCompletedSend(TCPClientState state)  
  339.         {  
  340.             if (CompletedSend != null)  
  341.             {  
  342.                 CompletedSend(thisnew AsyncEventArgs(state));  
  343.             }  
  344.         }  
  345.   
  346.         /// <summary>  
  347.         /// 网络错误事件  
  348.         /// </summary>  
  349.         public event EventHandler<AsyncEventArgs> NetError;  
  350.         /// <summary>  
  351.         /// 触发网络错误事件  
  352.         /// </summary>  
  353.         /// <param name="state"></param>  
  354.         private void RaiseNetError(TCPClientState state)  
  355.         {  
  356.             if (NetError != null)  
  357.             {  
  358.                 NetError(thisnew AsyncEventArgs(state));  
  359.             }  
  360.         }  
  361.   
  362.         /// <summary>  
  363.         /// 异常事件  
  364.         /// </summary>  
  365.         public event EventHandler<AsyncEventArgs> OtherException;  
  366.         /// <summary>  
  367.         /// 触发异常事件  
  368.         /// </summary>  
  369.         /// <param name="state"></param>  
  370.         private void RaiseOtherException(TCPClientState state, string descrip)  
  371.         {  
  372.             if (OtherException != null)  
  373.             {  
  374.                 OtherException(thisnew AsyncEventArgs(descrip, state));  
  375.             }  
  376.         }  
  377.         private void RaiseOtherException(TCPClientState state)  
  378.         {  
  379.             RaiseOtherException(state, "");  
  380.         }  
  381.  
  382.         #endregion  
  383.  
  384.         #region Close  
  385.         /// <summary>  
  386.         /// 关闭一个与客户端之间的会话  
  387.         /// </summary>  
  388.         /// <param name="state">需要关闭的客户端会话对象</param>  
  389.         public void Close(TCPClientState state)  
  390.         {  
  391.             if (state != null)  
  392.             {  
  393.                 state.Close();  
  394.                 _clients.Remove(state);  
  395.                 _clientCount--;  
  396.                 //TODO 触发关闭事件  
  397.             }  
  398.         }  
  399.         /// <summary>  
  400.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  401.         /// </summary>  
  402.         public void CloseAllClient()  
  403.         {  
  404.             foreach (TCPClientState client in _clients)  
  405.             {  
  406.                 Close(client);  
  407.             }  
  408.             _clientCount = 0;  
  409.             _clients.Clear();  
  410.         }  
  411.         #endregion  
  412.  
  413.         #region 释放  
  414.         /// <summary>  
  415.         /// Performs application-defined tasks associated with freeing,   
  416.         /// releasing, or resetting unmanaged resources.  
  417.         /// </summary>  
  418.         public void Dispose()  
  419.         {  
  420.             Dispose(true);  
  421.             GC.SuppressFinalize(this);  
  422.         }  
  423.   
  424.         /// <summary>  
  425.         /// Releases unmanaged and - optionally - managed resources  
  426.         /// </summary>  
  427.         /// <param name="disposing"><c>true</c> to release   
  428.         /// both managed and unmanaged resources; <c>false</c>   
  429.         /// to release only unmanaged resources.</param>  
  430.         protected virtual void Dispose(bool disposing)  
  431.         {  
  432.             if (!this.disposed)  
  433.             {  
  434.                 if (disposing)  
  435.                 {  
  436.                     try  
  437.                     {  
  438.                         Stop();  
  439.                         if (_listener != null)  
  440.                         {  
  441.                             _listener = null;  
  442.                         }  
  443.                     }  
  444.                     catch (SocketException)  
  445.                     {  
  446.                         //TODO  
  447.                         RaiseOtherException(null);  
  448.                     }  
  449.                 }  
  450.                 disposed = true;  
  451.             }  
  452.         }  
  453.         #endregion  
  454.     }  
  455. }  
客户端处理封装类
[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6.   
  7. namespace NetFrame.Net.TCP.Listener.Asynchronous  
  8. {  
  9.     public class TCPClientState  
  10.     {  
  11.         /// <summary>  
  12.         /// 与客户端相关的TcpClient  
  13.         /// </summary>  
  14.         public TcpClient TcpClient { getprivate set; }  
  15.   
  16.         /// <summary>  
  17.         /// 获取缓冲区  
  18.         /// </summary>  
  19.         public byte[] Buffer { getprivate set; }  
  20.   
  21.         /// <summary>  
  22.         /// 获取网络流  
  23.         /// </summary>  
  24.         public NetworkStream NetworkStream  
  25.         {  
  26.             get { return TcpClient.GetStream(); }  
  27.         }  
  28.   
  29.         public TCPClientState(TcpClient tcpClient, byte[] buffer)  
  30.         {  
  31.             if (tcpClient == null)  
  32.                 throw new ArgumentNullException("tcpClient");  
  33.             if (buffer == null)  
  34.                 throw new ArgumentNullException("buffer");  
  35.   
  36.             this.TcpClient = tcpClient;  
  37.             this.Buffer = buffer;  
  38.         }  
  39.         /// <summary>  
  40.         /// 关闭  
  41.         /// </summary>  
  42.         public void Close()  
  43.         {  
  44.             //关闭数据的接受和发送  
  45.             TcpClient.Close();  
  46.             Buffer = null;  
  47.         }  
  48.     }  
  49. }  
服务器事件参数类
[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace NetFrame.Net.TCP.Listener.Asynchronous  
  7. {  
  8.     /// <summary>  
  9.     /// 异步TcpListener TCP服务器事件参数类   
  10.     /// </summary>  
  11.     public class AsyncEventArgs:EventArgs  
  12.     {  
  13.          /// <summary>  
  14.         /// 提示信息  
  15.         /// </summary>  
  16.         public string _msg;  
  17.   
  18.         /// <summary>  
  19.         /// 客户端状态封装类  
  20.         /// </summary>  
  21.         public TCPClientState _state;  
  22.   
  23.         /// <summary>  
  24.         /// 是否已经处理过了  
  25.         /// </summary>  
  26.         public bool IsHandled { getset; }  
  27.   
  28.         public AsyncEventArgs(string msg)  
  29.         {  
  30.             this._msg = msg;  
  31.             IsHandled = false;  
  32.         }  
  33.         public AsyncEventArgs(TCPClientState state)  
  34.         {  
  35.             this._state = state;  
  36.             IsHandled = false;  
  37.         }  
  38.         public AsyncEventArgs(string msg, TCPClientState state)  
  39.         {  
  40.             this._msg = msg;  
  41.             this._state = state;  
  42.             IsHandled = false;  
  43.         }  
  44.     }  
  45. }  

本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处

这篇关于C#网络编程系列文章(三)之TcpListener实现异步TCP服务器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/319924

相关文章

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架