花了几天时间了解了SupperSocket工作原理,各各类之间的工作关系。SupperSocket大部资料网上都有,但写的都不适合初学者。

今天花点时间写下这几天的学习成果,一方面是为了将来更好的回顾知识点,另一方面想给初学者提供一份参考资料。考虑到笔功有限,

如果下面有什么信息不正确或写的不好,请大家多多包容!

  首先我贴一简单的代码。后面我会详细的说明工作原理和他们之间如何调用!下面的代码我也是从网上找的,相当简单。

我今天主要是讲解下SupperSocket的理解!

  1. public class TelnetServer : AppServer<TelnetSession>
  2. {
  3. protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
  4. {
  5. return base.Setup(rootConfig, config);
  6. }
  7.  
  8. protected override void OnStartup()
  9. {
  10. base.OnStartup();
  11. }
  12.  
  13. protected override void OnStopped()
  14. {
  15. base.OnStopped();
  16. }
  17. }
  1. public class TelnetSession : AppSession<TelnetSession>
  2. {
  3. protected override void OnSessionStarted()
  4. {
  5. //this.Send("Welcome to SuperSocket Telnet Server\r\n");
  6. byte[] bytes = Encoding.ASCII.GetBytes("Welcome\r\n to SuperSocket\r\n Telnet Server\r\n");
  7. this.Send(bytes, , bytes.Length);
  8. }
  9.  
  10. protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
  11. {
  12. this.Send("Unknow request");
  13. }
  14.  
  15. protected override void HandleException(Exception e)
  16. {
  17. this.Send("Application error: {0}", e.Message);
  18. }
  19.  
  20. protected override void OnSessionClosed(CloseReason reason)
  21. {
  22. //add you logics which will be executed after the session is closed
  23. base.OnSessionClosed(reason);
  24. }
  25. }
  1. public class ECHO : CommandBase<TelnetSession, StringRequestInfo>
  2. {
  3. public override void ExecuteCommand(TelnetSession session, StringRequestInfo requestInfo)
  4. {
  5. session.Send(requestInfo.Body);
  6. }
  7. }
  1. static void Main(string[] args)
  2. {
  3. Console.WriteLine("Press any key to start the server!");
  4.  
  5. Console.ReadKey();
  6. Console.WriteLine();
  7.  
  8. var appServer = new TelnetServer();
  9.  
  10. //Setup the appServer
  11. if (!appServer.Setup()) //Setup with listening port
  12. {
  13. Console.WriteLine("Failed to setup!");
  14. Console.ReadKey();
  15. return;
  16. }
  17.  
  18. Console.WriteLine();
  19.  
  20. //Try to start the appServer
  21. if (!appServer.Start())
  22. {
  23. Console.WriteLine("Failed to start!");
  24. Console.ReadKey();
  25. return;
  26. }
  27.  
  28. Console.WriteLine("The server started successfully, press key 'q' to stop it!");
  29.  
  30. while (Console.ReadKey().KeyChar != 'q')
  31. {
  32. Console.WriteLine();
  33. continue;
  34. }
  35.  
  36. //Stop the appServer
  37. appServer.Stop();
  38.  
  39. Console.WriteLine("The server was stopped!");
  40. Console.ReadKey();
  41. }

服务端代码就上面四部分,看起来很简单吧,但是大家真的看懂了吗,他们的工作原理是怎样的。命令 ECHO 这个类根本没有构造对象,他是怎样运行的?你越看越疑惑吧!

后面我会说明。

我还是先把客户端代码贴出来。代码简化了,如果大家不知道EasyClietn 可以使用Nuget搜索SuperSocket.ClientEngine、SuperSocket.ProtoBase

因为版本有很多,大家最好是用Nuget

  1. private void button1_Click(object sender, EventArgs e)
  2. {
  3. string strText = "add 1 1\r\n";
  4. if (client != null && client.IsConnected )
  5. {
  6. Byte[] smk = new Byte[strText.Length];
  7. for (int i = ; i < strText.Length; i++)
  8. {
  9. Byte ss = Convert.ToByte(strText[i]);
  10. smk[i] = ss;
  11. }
  12. byte[] b = Encoding.ASCII.GetBytes("ECHO 1 1\r\n");
  13. client.Send(smk.ToArray()); //EasyClient<MyPackageInfo> client
  14. }
  15. }
  1. byte[] b = Encoding.ASCII.GetBytes("ECHO 1 1\r\n");
  2. client.Send(smk.ToArray());
  3.  
  4. 给服务端发送了二进制的“ECHO 1 1\r\n" ,在这里给大家一个问题,为什么后面要加\r\n 换行符。大家带着问题继续往下看。
  5.  
  6. 现在给了大家两个问题?,现在我们来解决问题。
    服务端是如何接收到消息。其它大家可以不要具体体解,因为SupperStocket封闭了TCP 和 UDP 层。
  7.  
  8. SuperSocket.SocketEngine.AsyncStreamSocketSession 这个类是工作最底运类

从这个类可以知道数据的接收来源。

这个类是由

SuperSocket.SocketEngine.AsyncStreamSocketSession 《 SuperSocket.SocketEngine.AsyncSocketServer 《 SocketServerFactory 《 ProviderKey

《 ProviderFactoryInfo 《 AppDomainAppServer 《 DefaultBootstrap

  1. 这是最底层类,获取数据和发达送数据,这个大部分我们不要了解,因为这些都被AppSession封装起来了。 
  1.  

大家想了解的可以看下这个类。

  1. class AsyncStreamSocketSession : SocketSession, IAsyncSocketSessionBase, INegotiateSocketSession
  2. {
  3. private byte[] m_ReadBuffer;
  4. private int m_Offset;
  5. private int m_Length;
  6.  
  7. private bool m_IsReset;
  8.  
  9. public AsyncStreamSocketSession(Socket client, SslProtocols security, SocketAsyncEventArgsProxy socketAsyncProxy)
  10. : this(client, security, socketAsyncProxy, false)
  11. {
  12.  
  13. }
  14.  
  15. public AsyncStreamSocketSession(Socket client, SslProtocols security, SocketAsyncEventArgsProxy socketAsyncProxy, bool isReset)
  16. : base(client)
  17. {
  18. SecureProtocol = security;
  19. SocketAsyncProxy = socketAsyncProxy;
  20. var e = socketAsyncProxy.SocketEventArgs;
  21. m_ReadBuffer = e.Buffer;
  22. m_Offset = e.Offset;
  23. m_Length = e.Count;
  24.  
  25. m_IsReset = isReset;
  26. }
  27.  
  28. /// <summary>
  29. /// Starts this session communication.
  30. /// </summary>
  31. public override void Start()
  32. {
  33. //Hasn't started, but already closed
  34. if (IsClosed)
  35. return;
  36.  
  37. OnSessionStarting();
  38. }
  39.  
  40. private void OnSessionStarting()
  41. {
  42. try
  43. {
  44. OnReceiveStarted();
  45. m_Stream.BeginRead(m_ReadBuffer, m_Offset, m_Length, OnStreamEndRead, m_Stream);
  46. }
  47. catch (Exception e)
  48. {
  49. LogError(e);
  50. OnReceiveTerminated(CloseReason.SocketError);
  51. return;
  52. }
  53.  
  54. if (!m_IsReset)
  55. StartSession();
  56. }
  57.  
  58. private void OnStreamEndRead(IAsyncResult result)
  59. {
  60. var stream = result.AsyncState as Stream;
  61.  
  62. int thisRead = ;
  63.  
  64. try
  65. {
  66. thisRead = stream.EndRead(result);
  67. }
  68. catch (Exception e)
  69. {
  70. LogError(e);
  71. OnReceiveTerminated(CloseReason.SocketError);
  72. return;
  73. }
  74.  
  75. if (thisRead <= )
  76. {
  77. OnReceiveTerminated(CloseReason.ClientClosing);
  78. return;
  79. }
  80.  
  81. OnReceiveEnded();
  82.  
  83. int offsetDelta;
  84.  
  85. try
  86. {
  87. offsetDelta = AppSession.ProcessRequest(m_ReadBuffer, m_Offset, thisRead, true);
  88. }
  89. catch (Exception ex)
  90. {
  91. LogError("Protocol error", ex);
  92. this.Close(CloseReason.ProtocolError);
  93. return;
  94. }
  95.  
  96. try
  97. {
  98. if (offsetDelta < || offsetDelta >= Config.ReceiveBufferSize)
  99. throw new ArgumentException(string.Format("Illigal offsetDelta: {0}", offsetDelta), "offsetDelta");
  100.  
  101. m_Offset = SocketAsyncProxy.OrigOffset + offsetDelta;
  102. m_Length = Config.ReceiveBufferSize - offsetDelta;
  103.  
  104. OnReceiveStarted();
  105. m_Stream.BeginRead(m_ReadBuffer, m_Offset, m_Length, OnStreamEndRead, m_Stream);
  106. }
  107. catch (Exception exc)
  108. {
  109. LogError(exc);
  110. OnReceiveTerminated(CloseReason.SocketError);
  111. return;
  112. }
  113. }
  114.  
  115. private Stream m_Stream;
  116.  
  117. private SslStream CreateSslStream(ICertificateConfig certConfig)
  118. {
  119. //Enable client certificate function only if ClientCertificateRequired is true in the configuration
  120. if(!certConfig.ClientCertificateRequired)
  121. return new SslStream(new NetworkStream(Client), false);
  122.  
  123. //Subscribe the client validation callback
  124. return new SslStream(new NetworkStream(Client), false, ValidateClientCertificate);
  125. }
  126.  
  127. private bool ValidateClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
  128. {
  129. var session = AppSession;
  130.  
  131. //Invoke the AppServer's method ValidateClientCertificate
  132. var clientCertificateValidator = session.AppServer as IRemoteCertificateValidator;
  133.  
  134. if (clientCertificateValidator != null)
  135. return clientCertificateValidator.Validate(session, sender, certificate, chain, sslPolicyErrors);
  136.  
  137. //Return the native validation result
  138. return sslPolicyErrors == SslPolicyErrors.None;
  139. }
  140.  
  141. private IAsyncResult BeginInitStream(AsyncCallback asyncCallback)
  142. {
  143. IAsyncResult result = null;
  144.  
  145. var certConfig = AppSession.Config.Certificate;
  146. var secureProtocol = SecureProtocol;
  147.  
  148. switch (secureProtocol)
  149. {
  150. case (SslProtocols.None):
  151. m_Stream = new NetworkStream(Client);
  152. break;
  153. case (SslProtocols.Default):
  154. case (SslProtocols.Tls):
  155. case (SslProtocols.Ssl3):
  156. SslStream sslStream = CreateSslStream(certConfig);
  157. result = sslStream.BeginAuthenticateAsServer(AppSession.AppServer.Certificate, certConfig.ClientCertificateRequired, SslProtocols.Default, false, asyncCallback, sslStream);
  158. break;
  159. case (SslProtocols.Ssl2):
  160. SslStream ssl2Stream = CreateSslStream(certConfig);
  161. result = ssl2Stream.BeginAuthenticateAsServer(AppSession.AppServer.Certificate, certConfig.ClientCertificateRequired, SslProtocols.Ssl2, false, asyncCallback, ssl2Stream);
  162. break;
  163. default:
  164. var unknownSslStream = CreateSslStream(certConfig);
  165. result = unknownSslStream.BeginAuthenticateAsServer(AppSession.AppServer.Certificate, certConfig.ClientCertificateRequired, secureProtocol, false, asyncCallback, unknownSslStream);
  166. break;
  167. }
  168.  
  169. return result;
  170. }
  171.  
  172. private void OnBeginInitStreamOnSessionConnected(IAsyncResult result)
  173. {
  174. OnBeginInitStream(result, true);
  175. }
  176.  
  177. private void OnBeginInitStream(IAsyncResult result)
  178. {
  179. OnBeginInitStream(result, false);
  180. }
  181.  
  182. private void OnBeginInitStream(IAsyncResult result, bool connect)
  183. {
  184. var sslStream = result.AsyncState as SslStream;
  185.  
  186. try
  187. {
  188. sslStream.EndAuthenticateAsServer(result);
  189. }
  190. catch (IOException exc)
  191. {
  192. LogError(exc);
  193.  
  194. if (!connect)//Session was already registered
  195. this.Close(CloseReason.SocketError);
  196.  
  197. OnNegotiateCompleted(false);
  198. return;
  199. }
  200. catch (Exception e)
  201. {
  202. LogError(e);
  203.  
  204. if (!connect)//Session was already registered
  205. this.Close(CloseReason.SocketError);
  206.  
  207. OnNegotiateCompleted(false);
  208. return;
  209. }
  210.  
  211. m_Stream = sslStream;
  212. OnNegotiateCompleted(true);
  213. }
  214.  
  215. protected override void SendSync(SendingQueue queue)
  216. {
  217. try
  218. {
  219. for (var i = ; i < queue.Count; i++)
  220. {
  221. var item = queue[i];
  222. m_Stream.Write(item.Array, item.Offset, item.Count);
  223. }
  224.  
  225. OnSendingCompleted(queue);
  226. }
  227. catch (Exception e)
  228. {
  229. LogError(e);
  230. OnSendError(queue, CloseReason.SocketError);
  231. return;
  232. }
  233. }
  234.  
  235. protected override void OnSendingCompleted(SendingQueue queue)
  236. {
  237. try
  238. {
  239. m_Stream.Flush();
  240. }
  241. catch (Exception e)
  242. {
  243. LogError(e);
  244. OnSendError(queue, CloseReason.SocketError);
  245. return;
  246. }
  247.  
  248. base.OnSendingCompleted(queue);
  249. }
  250.  
  251. protected override void SendAsync(SendingQueue queue)
  252. {
  253. try
  254. {
  255. var item = queue[queue.Position];
  256. m_Stream.BeginWrite(item.Array, item.Offset, item.Count, OnEndWrite, queue);
  257. }
  258. catch (Exception e)
  259. {
  260. LogError(e);
  261. OnSendError(queue, CloseReason.SocketError);
  262. }
  263. }
  264.  
  265. private void OnEndWrite(IAsyncResult result)
  266. {
  267. var queue = result.AsyncState as SendingQueue;
  268.  
  269. try
  270. {
  271. m_Stream.EndWrite(result);
  272. }
  273. catch (Exception e)
  274. {
  275. LogError(e);
  276. OnSendError(queue, CloseReason.SocketError);
  277. return;
  278. }
  279.  
  280. var nextPos = queue.Position + ;
  281.  
  282. //Has more data to send
  283. if (nextPos < queue.Count)
  284. {
  285. queue.Position = nextPos;
  286. SendAsync(queue);
  287. return;
  288. }
  289.  
  290. OnSendingCompleted(queue);
  291. }
  292.  
  293. public override void ApplySecureProtocol()
  294. {
  295. var asyncResult = BeginInitStream(OnBeginInitStream);
  296.  
  297. if (asyncResult != null)
  298. asyncResult.AsyncWaitHandle.WaitOne();
  299. }
  300.  
  301. public SocketAsyncEventArgsProxy SocketAsyncProxy { get; private set; }
  302.  
  303. ILog ILoggerProvider.Logger
  304. {
  305. get { return AppSession.Logger; }
  306. }
  307.  
  308. public override int OrigReceiveOffset
  309. {
  310. get { return SocketAsyncProxy.OrigOffset; }
  311. }
  312.  
  313. private bool m_NegotiateResult = false;
  314.  
  315. void INegotiateSocketSession.Negotiate()
  316. {
  317. IAsyncResult asyncResult;
  318.  
  319. try
  320. {
  321. asyncResult = BeginInitStream(OnBeginInitStreamOnSessionConnected);
  322. }
  323. catch (Exception e)
  324. {
  325. LogError(e);
  326. OnNegotiateCompleted(false);
  327. return;
  328. }
  329.  
  330. if (asyncResult == null)
  331. {
  332. OnNegotiateCompleted(true);
  333. return;
  334. }
  335. }
  336.  
  337. bool INegotiateSocketSession.Result
  338. {
  339. get { return m_NegotiateResult; }
  340. }
  341.  
  342. private EventHandler m_NegotiateCompleted;
  343.  
  344. event EventHandler INegotiateSocketSession.NegotiateCompleted
  345. {
  346. add { m_NegotiateCompleted += value; }
  347. remove { m_NegotiateCompleted -= value; }
  348. }
  349.  
  350. private void OnNegotiateCompleted(bool negotiateResult)
  351. {
  352. m_NegotiateResult = negotiateResult;
  353.  
  354. //One time event handler
  355. var handler = Interlocked.Exchange<EventHandler>(ref m_NegotiateCompleted, null);
  356.  
  357. if (handler == null)
  358. return;
  359.  
  360. handler(this, EventArgs.Empty);
  361. }
  362. }
  1. SuperSocket.SocketEngine.AsyncStreamSocketSession  SuperSocket.SocketEngine.AsyncSocketServer SocketServerFactory  AppServerBase
  2.  
  3. SuperSocket.SocketBase.AppServerBase类里
  1. private bool SetupSocketServer()
  2. {
  3. try
  4. {
  5. m_SocketServer = m_SocketServerFactory.CreateSocketServer<TRequestInfo>(this, m_Listeners, Config);
  6. return m_SocketServer != null;
  7. }
  8. catch (Exception e)
  9. {
  10. if (Logger.IsErrorEnabled)
  11. Logger.Error(e);
  12.  
  13. return false;
  14. }
  15. }
  1.  
  1.  
  1. #region IActiveConnector
  2.  
  3. /// <summary>
  4. /// Connect the remote endpoint actively.
  5. /// </summary>
  6. /// <param name="targetEndPoint">The target end point.</param>
  7. /// <param name="localEndPoint">The local end point.</param>
  8. /// <returns></returns>
  9. /// <exception cref="System.Exception">This server cannot support active connect.</exception>
  10. Task<ActiveConnectResult> IActiveConnector.ActiveConnect(EndPoint targetEndPoint, EndPoint localEndPoint)
  11. {
  12. var activeConnector = m_SocketServer as IActiveConnector;
  13.  
  14. if (activeConnector == null)
  15. throw new Exception("This server cannot support active connect.");
  16.  
  17. return activeConnector.ActiveConnect(targetEndPoint, localEndPoint);
  18. }
  19.  
  20. /// <summary>
  21. /// Connect the remote endpoint actively.
  22. /// </summary>
  23. /// <param name="targetEndPoint">The target end point.</param>
  24. /// <returns></returns>
  25. /// <exception cref="System.Exception">This server cannot support active connect.</exception>
  26. Task<ActiveConnectResult> IActiveConnector.ActiveConnect(EndPoint targetEndPoint)
  27. {
  28. return ((IActiveConnector)this).ActiveConnect(targetEndPoint, null);
  29. }
  30.  
  31. #endregion IActiveConnector
  1.  
  1. private bool SetupSocketServer()
  2. {
  3. try
  4. {
  5. m_SocketServer = m_SocketServerFactory.CreateSocketServer<TRequestInfo>(this, m_Listeners, Config);
  6. return m_SocketServer != null;
  7. }
  8. catch (Exception e)
  9. {
  10. if (Logger.IsErrorEnabled)
  11. Logger.Error(e);
  12.  
  13. return false;
  14. }
  15. }
  1. private void SetupBasic(IRootConfig rootConfig, IServerConfig config, ISocketServerFactory socketServerFactory)
  2. {
  3. if (rootConfig == null)
  4. throw new ArgumentNullException("rootConfig");
  5.  
  6. RootConfig = rootConfig;
  7.  
  8. if (config == null)
  9. throw new ArgumentNullException("config");
  10.  
  11. if (!string.IsNullOrEmpty(config.Name))
  12. m_Name = config.Name;
  13. else
  14. m_Name = string.Format("{0}-{1}", this.GetType().Name, Math.Abs(this.GetHashCode()));
  15.  
  16. Config = config;
  17.  
  18. SetDefaultCulture(rootConfig, config);
  19.  
  20. if (!m_ThreadPoolConfigured)
  21. {
  22. if (!TheadPoolEx.ResetThreadPool(rootConfig.MaxWorkingThreads >= ? rootConfig.MaxWorkingThreads : new Nullable<int>(),
  23. rootConfig.MaxCompletionPortThreads >= ? rootConfig.MaxCompletionPortThreads : new Nullable<int>(),
  24. rootConfig.MinWorkingThreads >= ? rootConfig.MinWorkingThreads : new Nullable<int>(),
  25. rootConfig.MinCompletionPortThreads >= ? rootConfig.MinCompletionPortThreads : new Nullable<int>()))
  26. {
  27. throw new Exception("Failed to configure thread pool!");
  28. }
  29.  
  30. m_ThreadPoolConfigured = true;
  31. }
  32.  
  33. if (socketServerFactory == null)
  34. {
  35. var socketServerFactoryType =
  36. Type.GetType("SuperSocket.SocketEngine.SocketServerFactory, SuperSocket.SocketEngine", true);
  37.  
  38. socketServerFactory = (ISocketServerFactory)Activator.CreateInstance(socketServerFactoryType);
  39. }
  40.  
  41. m_SocketServerFactory = socketServerFactory;
  42.  
  43. //Read text encoding from the configuration
  44. if (!string.IsNullOrEmpty(config.TextEncoding))
  45. TextEncoding = Encoding.GetEncoding(config.TextEncoding);
  46. else
  47. TextEncoding = new ASCIIEncoding();
  48. }
  1. 请天就写到这里了,看到这里你可以结合源码应该能知道SuperSocket是如何发送数据和接收数据。当前接收的数据还是停留在
    TCP UDP层面上。下一稿将说明应用动,协议和命令是怎样工作。
  1.  

SupperSocket深入浅出(一)的更多相关文章

  1. SupperSocket深入浅出(二)

    如果还没有看SuperStock深入浅出(一) ,请先看 这一章,主要说下命令是如果运行的.刚开始的时候会发现拷别人的代码命令是可以运行的,在修改的过程中突然发现命令无效了? 这里什么原因?,我先把代 ...

  2. SupperSocket深入浅出

    这篇文章出要是SuperSocket底层如何接收数据 Process(ArraySegment<byte> segment) 获取加载数据(直到数据全部接收后返回) namespace S ...

  3. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  4. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  5. 深入浅出Struts2+Spring+Hibernate框架

    一.深入浅出Struts2 什么是Struts2? struts2是一种基于MVC的轻量级的WEB应用框架.有了这个框架我们就可以在这个框架的基础上做起,这样就大大的提高了我们的开发效率和质量,为公司 ...

  6. DOM 事件深入浅出(二)

    在DOM事件深入浅出(一)中,我主要给大家讲解了不同DOM级别下的事件处理程序,同时介绍了事件冒泡和捕获的触发原理和方法.本文将继续介绍DOM事件中的知识点,主要侧重于DOM事件中Event对象的属性 ...

  7. DOM 事件深入浅出(一)

    在项目开发时,我们时常需要考虑用户在使用产品时产生的各种各样的交互事件,比如鼠标点击事件.敲击键盘事件等.这样的事件行为都是前端DOM事件的组成部分,不同的DOM事件会有不同的触发条件和触发效果.本文 ...

  8. 深入浅出node(2) 模块机制

    这部分主要总结深入浅出Node.js的第二章 一)CommonJs 1.1CommonJs模块定义 二)Node的模块实现 2.1模块分类 2.2 路径分析和文件定位 2.2.1 路径分析 2.2.2 ...

  9. IOS 网络-深入浅出(一 )-> 三方SDWebImage

    首要我们以最为常用的UIImageView为例介绍实现原理: 1)UIImageView+WebCache:  setImageWithURL:placeholderImage:options: 先显 ...

随机推荐

  1. Debian下Cannot set LC_CTYPE to default locale: No such file or directory解决方法

    把语言环境变量改为英文 将Ubuntu系统语言环境改为英文的en_US.UTF-8 查看当前系统语言环境 locale 编辑配置文件,将zh_US.UTF-8改为en_US.UTF-8,zh改为en ...

  2. BZOJ1563:[NOI2009]诗人小G(决策单调性DP)

    Description Input Output 对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度若最小的不协调度超过1018,则输出"Too hard to arr ...

  3. 【[HEOI2016/TJOI2016]字符串】

    码农题啊 上来先无脑一个\(SA\)的板子,求出\(SA\)和\(het\)数组 我们只需要从\(sa[i]\in[a,b]\)的所有\(i\)中找到一个\(i\)使得\(sa[i]\)和\(rk[c ...

  4. PHP面试系列 之框架(二)---- 常见框架的特性

    题:PHP框架有哪些,你用过哪些?各自的优缺点是什么? 考点: (1)PHP框架的差异和优缺点 1.Yaf框架 使用PHP扩展的形式写的一个PHP框架,也就是以C语言为底层编写的,性能上要比PHP代码 ...

  5. AWR报告分析

    AWR报告分析 awr报告是oracle 10g下提供的一种性能收集和分析工具,它能提供一个时间段内整个系统资源使用情况的报告,通过这个报告,我们就可以了解一个系统的整个运行情况,这就像一个人全面的体 ...

  6. 微服务之配置中心ConfigKeeper

    在微服务架构中,配置中心是必不可少的基础服务.ConfigKeeper已开源,本文将深度分析配置中心的核心内容,错过「Spring Cloud中国社区北京沙龙-2018.10.28 」的同学将从本篇文 ...

  7. eclipse中svn插件装好后出现"位置错误"的处理

    错误现象: 验证位置时发生错误:"org.apache.subversion.javahl.ClientException:svn:E210004: Number is larger tha ...

  8. oracle 11G dataguard 恢复

    检查主备机的sys 密码是否一致,忘记密码可以修改,同步 .alter user sys identified by xxx: orapwd file=oraxxx.ora password=admi ...

  9. 如何设计处优秀的Restful API

    只知道遵规循矩的程序员是假程序员,任何技术都是不断发明创造改进的. 如何设计处优秀的Restful API?  盲目跟风,设计糟糕的Resful API = 浪费时间 ! 不啰嗦,直接进入技术主题: ...

  10. ThinkPHP微信扫码支付接口

    最近折腾微信扫码支付,看了微信官方文档,找了很多网页,发现和文档/demo不匹配,现在自己算是弄出来了(文件名称有所更改),贴出来分享一下 一.将有用的官方lib文件和使用的相关文件放置到vendor ...