【问题标题】:UDPClient Receive method not working in a serviceUDPClient 接收方法在服务中不起作用
【发布时间】:2010-02-19 18:58:06
【问题描述】:

我一直在试验 C# 中的 UDP 发送和接收,但遇到了一个奇怪的问题。该代码在控制台应用程序中运行良好,但是当我尝试在服务中使用完全相同的代码时,client.Receive 方法被阻止。该服务正常运行并且不会中止,并且我已将写入记录写入文本文件,因此我知道它会到达接收。谁有想法?下面的代码...

public partial class Service1 : ServiceBase
{
    private bool serviceStarted = false;
    Thread listenerThread;

    public Service1()
    {
        InitializeComponent();      
    }

    protected override void OnStart(string[] args)
    {
        serviceStarted = false;
        WriteLog("UDPListener Service Starting");

        ThreadStart thread = new ThreadStart(StartListening);
        listenerThread = new Thread(thread);

        serviceStarted = true;
        listenerThread.Start();
    }

    protected override void OnStop()
    {
        WriteLog("UDPListener Service Stopping");

        serviceStarted = false;
        listenerThread.Join(new TimeSpan(0, 0, 5));
    }

    private void StartListening()
    {
        WriteLog("Worker thread spawned.");

        UdpClient client = new UdpClient(40000);

        while (serviceStarted)
        {
            WriteLog("Service is started.  Getting endpoint.");
            IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 40000);
            WriteLog("Thread is listening...");

            byte[] content = client.Receive(ref remoteIPEndPoint);
            WriteLog("Receive unblocked.");

            if (content.Length > 0)
            {
                string message = Encoding.ASCII.GetString(content);
                WriteLog("UDPListener Message = " + message);
            }
        }
        Thread.CurrentThread.Abort();
    }

    private void WriteLog(string strMessage)
    {
        FileStream filestream = new FileStream(@"c:\temp\UDPClientLog.txt", 
                                       FileMode.OpenOrCreate, 
                                       FileAccess.Write);
        StreamWriter streamwriter = new StreamWriter(filestream);
        streamwriter.BaseStream.Seek(0, SeekOrigin.End);

        streamwriter.WriteLine(DateTime.Now.ToLongDateString() +
            " at " +
            DateTime.Now.ToLongTimeString() +
            ": " +
            strMessage +
            "\n");

        streamwriter.Flush();
        streamwriter.Close();
    }
}

【问题讨论】:

    标签: c# service udpclient


    【解决方案1】:

    终于想通了。 Windows 防火墙正在阻止传入连接,并且显然不允许该服务以交互方式请求取消阻止它的权限。

    【讨论】:

      【解决方案2】:

      那是因为UdpClient.Receive 正在阻塞(即同步)操作,线程会被阻塞,直到你收到数据:

      Receive 方法将阻塞,直到数据报从远程主机到达。当数据可用时,Receive 方法将读取第一个入队的数据报,并将数据部分作为字节数组返回。此方法使用发送者的 IPAddress 和端口号填充 remoteEP 参数。

      如果您想要非阻塞行为,您可以使用异步版本:UdpClient.BeginReceive 方法。

      【讨论】:

      • 对不起,应该澄清一下。我知道 Receive 应该被阻止,但它永远不会收到来自发件人的消息。这只发生在服务中,控制台应用程序中的相同代码正确接收消息。
      • 嗯.. 很奇怪,因为我使用 iwindows 服务和 UDP 套接字并且一切正常。你确定你收到数据吗?像wireshark这样的工具可以证明这一点......
      • 我很确定它没有接收数据,或者我认为 Receive 方法会返回。线程正在生成并且端点已正确建立(两个日志条目都显示)。一切看起来都很好 - 服务已启动并且事件查看器中没有错误 - 但它只是坐在那里等待它永远不会收到的消息。它应该可以工作,因为控制台执行完全相同的操作(创建一个新线程等)并且它可以很好地获取消息。我被难住了。
      • 还有一个建议:您可以创建单独的类来完成所有工作并在控制台应用程序中对其进行测试。比您可以在 Windows 服务中使用相同的类(不相似的逻辑)。它也应该工作。也许存在一些与安全相关的问题?
      • 检查服务在哪个账户下运行。使用您的管理员帐户对其进行测试。
      【解决方案3】:

      无需关闭窗口防火墙,只需将您的程序添加到“允许的程序”中

      例如,如果您的服务运行位置是“C:\Program Files (x86)\MyWork\Service1.exe”

      转到防火墙单击左上角的“允许程序或功能通过窗口防火墙”。 点击“允许其他程序” 单击“浏览”选择您的程序,例如服务1.exe 点击“添加” 它会出现在您的“允许程序和功能列表”下。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-26
        相关资源
        最近更新 更多