2016-06-07 67 views
0

我有一个特殊的套接字监听器,它在它的线程中工作。从外部程序获取更新数据库的命令是工作。当命令来到套接字我打电话特殊的方法,从数据库更新我的应用程序缓存。来自套接字监听器的处理命令的延迟

我有一个问题,即从外部程序发送命令和在我的应用程序(ASP .NET应用程序)中处理该命令之间的延迟。每天我的应用程序都会在凌晨4点重新开始,到今天结束时,我会延迟大约1-2个小时。

我该如何减少这种延迟?

您可以在下方找到我的听众代码。

谢谢。

public delegate void OnECIGetCommand(string command); 

public class ECIMain 
{ 

    protected Socket socket; 
    protected string ip; 
    protected int port; 

    private static ECIMain INSTANCE = null; 

    const int receivedDataSize = 250; 
    protected static byte[] buffer = new byte[ receivedDataSize ]; 
    protected static StringBuilder sb;        

    protected static DoWorkEventHandler onCommand;    

    private ECIMain() 
    { 
     socket = new Socket(AddressFamily.InterNetwork, 
        SocketType.Stream, ProtocolType.Tcp); 
     sb = new StringBuilder(); 
    } 

    private void StartSocket() 
    { 
     sb.Clear(); 
     socket.Listen(1); 
     socket.BeginAccept(null, receivedDataSize, 
       new AsyncCallback(AcceptReceiveDataCallback), socket); 
    } 

    private static void AcceptReceiveDataCallback(IAsyncResult ar) 
    { 
     // Get the socket that handles the client request. 
     Socket listener = (Socket)ar.AsyncState; 

     // End the operation and display the received data on the console. 
     byte[] Buffer; 
     int bytesTransferred; 
     Socket handler = listener.EndAccept(out Buffer, 
         out bytesTransferred, ar); 
     HandleBuff(bytesTransferred, Buffer); 

     // Create the state object for the asynchronous receive. 
     handler.BeginReceive(buffer, 0, receivedDataSize, 
       SocketFlags.None, new AsyncCallback(ReadCallback), handler); 
    } 

    private static void HandleBuff(int size, byte[] buff) 
    { 
     if (size > 0) 
     { 
      // There might be more data, so store the data received so far. 
      sb.Append(Encoding.ASCII.GetString(buff, 0, size)); 

      // Check for end-of-file tag. If it is not there, read more data. 
      var content = sb.ToString(); 
      int pos = -1; 
      if ((pos = content.IndexOf("</cmd>")) > -1) 
      { 
       // All the data has been read from the 
       // client. 
       pos += 6; 
       if(pos < content.Length) 
        content = content.Remove(pos); 


       var startPos = content.LastIndexOf("<cmd>"); 
       if(startPos > -1) 
       { 
        if (startPos > 0)  
          content = content.Remove(0, startPos); 
        BackgroundWorker worker = new BackgroundWorker(); 
        worker.DoWork += onCommand; 
        worker.RunWorkerAsync(content); 

       } 
       sb.Remove(0, pos); 
      } 
     } 
    } 

    private static void ReadCallback(IAsyncResult ar) 
    { 
     // Retrieve the state object and the handler socket 
     // from the asynchronous state object. 
     Socket handler = (Socket)ar.AsyncState; 
     SocketError error; 
     // Read data from the client socket. 
     int bytesRead = handler.EndReceive(ar, out error); 

     if (error == SocketError.Success) 
     { 
      if (bytesRead > 0) 
      { 
       HandleBuff(bytesRead, buffer); 
       handler.BeginReceive(buffer, 0, receivedDataSize, 
         SocketFlags.None, new AsyncCallback(ReadCallback), handler); 
      } 
      else 
      { 
       handler.Disconnect(true); 
       INSTANCE.StartSocket(); 
      } 
     } 
     else if (error == SocketError.Shutdown || error == SocketError.ConnectionReset) 
     { 
      INSTANCE.StartSocket(); 
     } 
    } 

    public static string InitECI(int port, DoWorkEventHandler commandHandler) 
    { 
     if (INSTANCE == null) 
     { 
      INSTANCE = new ECIMain(); 
      INSTANCE.port = port; 
      onCommand += commandHandler; 
      IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); 
      IPAddress ipAddress = ipHostInfo.AddressList 
        .FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork); 
      IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port); 
      INSTANCE.ip = ipAddress.ToString(); 
      try 
      { 
       INSTANCE.socket.Bind(localEndPoint); 
      } 
      catch (System.Net.Sockets.SocketException e) 
      { 
       if (e.SocketErrorCode == System.Net.Sockets 
             .SocketError.AddressAlreadyInUse) 
       { 
        //INSTANCE.socket.Bind(localEndPoint); 
       } 
       throw e; 
      } 
      INSTANCE.StartSocket(); 
     } 
     return INSTANCE.ip; 
    } 

    public static void ShutDownECI() 
    { 
     if(INSTANCE.socket.Connected) 
      INSTANCE.socket.Disconnect(false); 
     INSTANCE.socket.Close(); 
    } 
} 

回答

0

当使用TCP协议栈(发送或接收),我们必须看看堆栈它自己的系统,这是防弹,而且运作非常好......大多数这类问题的处理事实即应用层能够轻松地根据需要启动尽可能多的异步操作,但这并不意味着TCP堆栈将变得更快,特别是如果它不堪重负的话。这意味着它会尽可能排队并处理任务。

被压倒的堆栈的症状之一是通过Netstat命令可视化存在的许多半会话状态。任何具有“等待”一词的内容都是半个状态的指标。这发生在一方发布数据包但另一方不立即响应时发生。从那里开始,所有这一切都是艰难的,因为TCP开始运行,并试图通过重新发送相同的数据包来保持会话活跃。将此数乘以活动会话的数量,以及在超时之前每个数据包TCP重试次数高达10次的事实,您可以看到这是堆栈需要的最后一件事。

您的情况可能是网络流量超过单个网络适配器的容量。这通常通过添加更多网卡并使用其他方式来进行负载平衡来解决。其中一种方法就是他们称之为循环法的DNS,它是最便宜的。另一种方式是F5设备。

底线,这听起来像你的网络适配器正在被淹没。

这里有几件事要检查电线的两侧。

  • 当演出开始时,所有插座都完全关闭吗?
  • 您是否能够运行网络监视器来查看总体负载...您通常希望在任何单个网络适配器上的利用率达到60%或更低。
  • 如果你的负荷过高,那么你可以跟DNS人关于使用循环赛,并以另一种卡插入同一台服务器(这将有不同的地址)
  • 有时是由于缺乏数据的压缩被送到电线上。您也可以调查压缩技术。
  • 有时候交换机会变坏,从而导致MAC-MAC连接能力。
  • 错误的路由器配置可以允许从不同的接入点重新传输线路。
  • 配置错误的服务器也可能会传播过多的噪音(总垃圾)
  • 无线接入点臭名昭着,它们可能也是噪声源。

找到这类问题的根源有很多,但希望其中的一些想法能帮助您。