首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ManualResetEvent在windows服务中停止套接字程序

ManualResetEvent在windows服务中停止套接字程序
EN

Stack Overflow用户
提问于 2014-03-20 05:45:02
回答 1查看 1.2K关注 0票数 0

我有一个windows服务,它根据我的要求使用TCP/IP protocol.As监视套接字--我的代码是建立到机器的连接并从那里接收数据--这是我一直想要的,这就是为什么我在windows service.But中做到了这一点--我面临的问题是,在自动停止从端口读取之后,服务读取套接字端口3-4小时,而我从Services.msc获得的服务状态显示它正在运行。

这是我的windows服务代码。

代码语言:javascript
运行
复制
    string ipaddress, textfileSaveLocation;
    Byte[] bBuf;
    string buf;
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    private System.Threading.Thread _thread;
    private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);

    string df = "";

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }
    protected override void OnStart(string[] args)
    {
        _thread = new Thread(DoWork);
        _thread.Start();

    }
    private void DoWork()
    {
        // create and monitor socket here...

        ipaddress = "192.168.1.100";
        int port = int.Parse("8181");

        byte[] data = new byte[1024];
        string stringData;
        string input;

        IPAddress ipadd = IPAddress.Parse(ipaddress);
        IPEndPoint ipend = new IPEndPoint(ipadd, port);

        sock.NoDelay = false;
        try
        {            
            sock.Connect(ipend);
        }
        catch (Exception dfg)
       {

            return;
        }
        try
        {
            input = "Client here";
            sock.Send(Encoding.ASCII.GetBytes(input));

            while (!_shutdownEvent.WaitOne(0))
            {                  
                data = new byte[1024];
                int recv = sock.Receive(data);
                stringData = Encoding.ASCII.GetString(data, 0, recv);

            }

        }
        catch (Exception DFGFD)
        {
        }

    }

    protected override void OnStop()
    {
        sock.Shutdown(SocketShutdown.Both);
        sock.Close();

        _shutdownEvent.Set();
        _thread.Join();  // wait for thread to stop
    }
}
}

为什么我的服务在3-4小时后停止接收数据?请帮助我解决这个问题。

下面是我将ServerMachine数据插入文本文件的代码。

代码语言:javascript
运行
复制
                        try
                        {
                            FileStream fs = new FileStream(textfileSaveLocation, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
                            StreamWriter swr = new StreamWriter(textfileSaveLocation,true);
                            swr.WriteLine(stringData);
                            swr.Close();
                            swr.Dispose();
                            fs.Close();
                            fs.Dispose();
                        }
                        catch (Exception Ex)
                        {

                        }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-20 15:12:16

正如@nobugz所指出的,您有两个问题。

首先,您正在吞咽发生在DoWork()中的任何异常。你在抓他们,是的,但你没有报告他们。为什么过了几个小时就停下来了?服务器可能已经关闭,这将终止套接字连接。您没有尝试重新连接,所以线程退出,但是进程继续运行。放置一些异常报告,以了解为什么套接字关闭,然后相应地处理它。

这就引出了第二点,即你没有恢复能力。一旦出现异常或套接字因某种原因优雅关闭,您的线程就会退出。如果您希望它持续工作,那么您将需要添加一些逻辑,以便在发生问题的情况下重新连接。换句话说,DoWork()退出的唯一原因是一个关闭事件。否则,它将需要循环,在出现错误时尝试重新连接。正如@nobugz所说,这还需要您重置ManualResetEvent,以便在重新连接时您的接收循环将按预期工作。但是,您不需要在Reset()回调中调用OnStart(),因为您已经将_shutdownEvent初始化为false,这正是Reset()所做的。

HTH。

编辑:

这是袖口上的,所以我不会验证它的准确性。我会解决你(或其他人)可能发现的任何问题。

为关闭通知定义一个ManualResetEvent对象。将OnStart()回调更改为:

代码语言:javascript
运行
复制
using System.Threading;

ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
Thread _thread;

protected override void OnStart(string[] args)
{
    // Create the thread and start it.
    _thread = new Thread(DoWork);
    _thread.Start();
}

由于您需要一个TCP连接,所以我强烈建议使用TcpClient而不是Socket。将DoWork()回调更改为如下所示:

代码语言:javascript
运行
复制
using System.Net.Sockets;

private void DoWork()
{
    while (!_shutdownEvent.WaitOne(0))
    {
        TcpClient client = new TcpClient();

        try
        {
            // This is a blocking call.  You might want to consider one of the
            // asynchronous methods...
            client.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8181));
        }
        catch (Exception ex)
        {
            // Log the error here.
            client.Close();
            continue;
        }

        try
        {
            using (NetworkStream stream = client.GetStream())
            {
                byte[] notify = Encoding.ASCII.GetBytes("Client here");
                stream.Write(notify, 0, notify.Length);

                byte[] data = new byte[1024];
                while (!_shutdownEvent.WaitOne(0))
                {
                    int numBytesRead = stream.Read(data, 0, data.Length);
                    if (numBytesRead > 0)
                    {
                        string msg = Encoding.ASCII.GetString(data, 0, numBytesRead);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // Log the error here.
            client.Close();
        }
    }
}

最后,在OnStop()回调中,触发线程关闭:

代码语言:javascript
运行
复制
protected override void OnStop()
{
    _shutdownEvent.Set();  // trigger the thread to stop
    _thread.Join();        // wait for thread to stop
}

现在,了解TCP通信是基于流的非常重要.这意味着,每次读取套接字(例如,TcpClient)时,都不能保证接收完整的消息。如果服务器发送回消息“客户端通知接收”,最初读取套接字可能只会得到"Client“。随后的阅读可能会得到“再读”。第三次阅读可能会被“否决”。这取决于您在一起缓冲读取,然后处理消息。大多数协议将使用某种类型的报头来指示消息的类型和长度。如果您只是使用字符串,那么消息的类型就不重要了,因为所有东西都是字符串。此外,知道字符串的结束位置可以使用空终止符来完成,而不是例如在长度前加上前缀。只需知道,读取TCP套接字可能只得到您期望接收的消息的一部分。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22524398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档