2013-06-04 3 views
1

Вот мой код очень простой TCP-сервер (в основном образец Асинхронный сервер Оправа пример - http://goo.gl/Ix5C - слегка видоизмененный):TCP сервер в C# вызывает 100% загрузку процессора через 2-3 дня

public static void InitiateListener() 
    { 
     try 
     { 
      allDone = new ManualResetEvent(false); 
      configFile = new XmlConfig();     
      StartListening(); 
     } 
     catch (Exception exc) 
     { 
      LogsWriter f = new LogsWriter(configFile.ErrorLogsPath); 
      f.WriteToFile(exc.Message); 
      f.CloseFile(); 
     } 

    } 

    private static void StartListening() 
    {  
     try 
     { 
      IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, configFile.Port); 
      Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

      listener.Bind(localEndPoint); 
      listener.Listen(100);     

      while (true) 
      { 
       // Set the event to nonsignaled state. 
       allDone.Reset();      

       // Start an asynchronous socket to listen for connections. 
       listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

       // Wait until a connection is made before continuing. 
       allDone.WaitOne(); 
      } 
     } 
     catch (Exception exc) 
     { 
      throw exc; 
     } 
    } 

    public static void AcceptCallback(IAsyncResult ar) 
    { 
     allDone.Set(); // Signal the main thread to continue.    

     // Get the socket that handles the client request. 
     Socket listener = (Socket)ar.AsyncState; 
     Socket handler = listener.EndAccept(ar); 

     // Create the state object. 
     StateObject state = new StateObject(); 
     state.workSocket = handler; 

     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 
    } 

    public static void ReadCallback(IAsyncResult ar) 
    { 
     string hexData = string.Empty; 

     // Retrieve the state object and the handler socket from the asynchronous state object. 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.workSocket; 

     try 
     { 
      // Read data from the client socket. 
      int bytesRead = handler.EndReceive(ar);     

      if (bytesRead > 0) 
      { 
       hexData = BitConverter.ToString(state.buffer); 

       if (hexData.Contains("FA-F8")) //heartbeat - echo the data back to the client. 
       { 
        byte[] byteData = state.buffer.Take(bytesRead).ToArray(); 
        handler.Send(byteData); 
       } 
       else if (hexData.Contains("0D-0A")) //message 
       { 
        state.AsciiData = Encoding.ASCII.GetString(state.buffer, 0, bytesRead); 
        state.ParseMessage(configFile); 
       } 
      } 
      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);     
     } 
     catch (Exception) 
     { 
      handler.Shutdown(SocketShutdown.Both); 
      handler.Close(); 
     } 
    } 

Это все в службе Windows. И CPU достигает 100% после примерно двух с половиной дней работы вполне приемлемо. Это произошло 3 раза сейчас - служба Windows всегда работает нормально и функционирует так, как она должна, используя почти не ресурсы ЦП, но когда-то на 3-й день идет на 100% и остается там до тех пор, пока служба не будет перепрограммирована.

Я получаю очень простые CSV-пакеты, которые я быстро анализирую и отправляю их в базу данных через webservice в этом методе: state.ParseMessage (configFile); Даже когда процессор 100%, база данных заполняется довольно надежно. Но я понимаю, это может быть одно место, где мне нужно исследовать?

Какие другие области кода выглядят как они могут быть причиной проблемы? Я новичок в асинхронном программировании, поэтому не знаю, нужно ли мне вручную закрывать потоки. Кроме того, это может быть другой проблемой: handler.BeginReceive (state.buffer, 0, StateObject.BufferSize, 0, новый AsyncCallback (ReadCallback), состояние);
Вызов этой строки в самом ReadCallback. Я делаю это, чтобы поддерживать соединение с клиентом и продолжать получать данные, но, возможно, мне нужно закрыть сокет и заставить новое соединение?

Не могли бы вы предложить несколько предложений? Благодаря

+1

Когда он идет на 100%, служба все еще работает с точки зрения прослушивания запросов? Интересно, умирает ли слушатель, заставляя «BeginAccept» немедленно запускать ваш обратный вызов, а затем, когда вы вызываете «EndAccept», вы получаете исключение. –

+1

В «Мониторе ресурсов» вашего компьютера вы можете отслеживать количество потоков, используемых приложением. Вы могли видеть, растет ли это число с течением времени, хотя я действительно не думаю, что это может быть проблемой. – C4stor

+0

Привет, Джон, сервис по-прежнему функционирует должным образом, когда он идет на 100%. Информация из новых пакетов вводится в базу данных, и все это кажется правильным. Функциональность не кажется проблемой в любой момент. – Sundance

ответ

0

Вместо петли while(true) в методе startlistening мы должны вызвать

listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

от метода AcceptCallback раза завершения принятия нового клиента.

0

Вам необходимо обнаружить отключение через bytesRead == 0. Прямо сейчас вы этого не делаете и вместо этого читаете.

Похоже, вы скопировали образец кода MSDN. Я могу сказать из-за беспроблемного сочетания асинхронного ввода-вывода и событий. Весь этот код становится проще при использовании синхронного ввода-вывода.