2011-05-03 184 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()完成,这不会在超时期限内完成。您应该开始异步收听或将列表代码推送到另一个线程。