2011-05-03 182 views
0

我有一個異步套接字監聽器類,像這樣:無法啓動Windows服務

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

using log4net; 
using log4net.Config; 
using log4net.Repository; 
using log4net.Appender; 


namespace GatewayWindowsService.Code 
{ 


    // State object for reading client data asynchronously 
    public class ListenerStateObject 
    { 
     // Client socket. 
     public Socket workSocket = null; 
     // Size of receive buffer. 
     public const int BufferSize = 1024; 
     // Receive buffer. 
     public byte[] buffer = new byte[BufferSize]; 
     // Received data string. 
     public StringBuilder sb = new StringBuilder(); 
    } 

    public class AsynchronousSocketListener 
    { 
     // The address for the remote device 
     private const string address = "172.25.17.119"; 

     // The port number for the remote device. 
     private const int port = 11000; 

     //LOG4NET LOG 
     private ILog log; 

     // Thread signal. 
     public static ManualResetEvent allDone = new ManualResetEvent(false); 

     public AsynchronousSocketListener(ILog log) 
     { 
      this.log = log; 
     } 

     public void StartListening() 
     { 

      // Data buffer for incoming data. 
      byte[] bytes = new Byte[1024]; 

      // Establish the local endpoint for the socket. 
      // The DNS name of the computer 
      // running the listener is "host.contoso.com". 
      IPHostEntry ipHostInfo = Dns.Resolve(address); 
      IPAddress ipAddress = ipHostInfo.AddressList[0]; 
      IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port); 

      // Create a TCP/IP socket. 
      Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

      // Bind the socket to the local endpoint and listen for incoming connections. 
      try 
      { 
       listener.Bind(localEndPoint); 
       listener.Listen(100); 

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

       // Start an asynchronous socket to listen for connections. 

       log.Info("Waiting for a connection..."); 
       listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

       // Wait until a connection is made before continuing. 
       allDone.WaitOne(); 
       //} 

      } 
      catch (Exception e) 
      { 
       log.Error(e.ToString()); 
      } 

     } 

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

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

      // Create the state object. 
      ListenerStateObject state = new ListenerStateObject(); 
      state.workSocket = handler; 
      handler.BeginReceive(state.buffer, 0, ListenerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 
     } 

     public void ReadCallback(IAsyncResult ar) 
     { 
      String content = String.Empty; 

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

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

      if (bytesRead > 0) 
      { 
       // There might be more data, so store the data received so far. 
       state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 

       // Check for end-of-file tag. If it is not there, read 
       // more data. 
       content = state.sb.ToString(); 
       if (content.IndexOf("<EOF>") > -1) 
       { 
        // All the data has been read from the 
        // client. Display it on the console. 

        log.Info("Read " + content.Length + " bytes from socket. \n Data : " + content); 
        // Echo the data back to the client. 
        Send(handler, content); 
       } 
       else 
       { 
        // Not all data received. Get more. 
        handler.BeginReceive(state.buffer, 0, ListenerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 
       } 
      } 
     } 

     private void Send(Socket handler, String data) 
     { 
      // Convert the string data to byte data using ASCII encoding. 
      byte[] byteData = Encoding.ASCII.GetBytes(data); 

      // Begin sending the data to the remote device. 
      handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); 
     } 

     private void SendCallback(IAsyncResult ar) 
     { 
      try 
      { 
       // Retrieve the socket from the state object. 
       Socket handler = (Socket)ar.AsyncState; 

       // Complete sending the data to the remote device. 
       int bytesSent = handler.EndSend(ar); 
       log.Info("Sent " + bytesSent + " bytes to client."); 

       handler.Shutdown(SocketShutdown.Both); 
       handler.Close(); 

      } 
      catch (Exception e) 
      { 
       log.Error(e.ToString()); 
      } 
     } 

} 

}

現在我用一個窗口服務這一類實例化它是這樣的:

//EXECUTED WHEN THE WINDOWS SERVICE IS STARTED 
     protected override void OnStart(string[] args) 
     { 
      log.Info("Windos Service Initiated");      

      sListener = new AsynchronousSocketListener(log); 
      sListener.StartListening(); 
     } 

當我嘗試從服務中啓動這個服務時,進度條會一直走,最後我得到這個錯誤:

Windows could not start the Gateway Windows Service on Local Computer Error 1053: The service did not respond to the start or control request in a timely fashion

我該如何解決這個問題,用socket監聽啓動windows服務?

感謝

回答

0

這是不正確的方式來阻止Windows服務的OnStart()函數。你只在這個函數中進行初始化並返回。所以正確的方法是你應該從OnStart()函數啓動一個新線程並返回。您應該監聽新創建的線程中的傳入連接。

這是您修改的函數來運行一個單獨的線程。

protected override void OnStart(string[] args) 
{ 
    log.Info("Windos Service Initiated"); 

    sListener = new AsynchronousSocketListener(log); 

    // Create a new thread. Its better if you declare myThread as class variable. 
    Thread myThread = new Thread(new ThreadStart(sListener.StartListening)); 
    myThread.Start(); 
} 

請忽略代碼中是否存在某些語法或拼寫錯誤。我目前正在使用Mac,並沒有Visual Studio :)

+0

一個例子會很好;) – RedEagle 2011-05-03 09:04:57

+0

我編輯了我的文章並添加了示例代碼......請參閱上文。 :) – Tayyab 2011-05-03 10:20:53

0

你的聽衆等待中StartListening()的連接。 services.msc-Panel等待OnStart()完成,這不會在超時期限內完成。您應該開始異步收聽或將列表代碼推送到另一個線程。