2

我一直在试验 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();
    }
}
4

3 回答 3

8

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

于 2010-02-19T22:42:17.123 回答
0

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

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

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

于 2010-02-19T19:47:56.710 回答
0

而不是关闭窗口防火墙简单地将您的程序添加到“允许的程序”

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

转到防火墙单击左上角的“允许程序或功能通过窗口防火墙”。单击“允许另一个程序” 单击“浏览”选择您的程序,例如 Service1.exe 单击“添加”,它将出现在“允许程序和功能列表”下。

于 2015-06-11T15:38:03.710 回答