UDPClient 接收方法在服务中不起作用
我一直在尝试用 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();
}
}
I've been experimenting the UDP sending and receiving in C# and have a strange issue. The code works fine in a console app, but the client.Receive method is blocked when I try to use the exact same code in a Service. The Service runs normally and doesn't abort, and I have logging writing to a text file, so I know it gets to the Receive. Anyone have any ideas? Code below...
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
终于明白了这一点。 Windows 防火墙正在阻止传入连接,显然该服务不允许以交互方式请求解锁它的权限。
Finally figured this out. Windows Firewall was blocking the incoming connection and apparently the service isn't allowed to interactively ask for permission to unblock it.
这是因为 UdpClient.Receive 是阻塞(即同步)操作,并且线程将被阻塞,直到您接收到数据:
Receive 方法将阻塞,直到数据报从远程主机到达。当数据可用时,Receive 方法将读取第一个排队的数据报并将数据部分作为字节数组返回。此方法使用发送者的 IP 地址和端口号填充 RemoteEP 参数。
如果您想要非阻塞行为,可以使用异步版本:UdpClient.BeginReceive 方法。
That's because UdpClient.Receive is blocking (i.e. synchronous) operation, and thread would be blocked until you receive data:
The Receive method will block until a datagram arrives from a remote host. When data is available, the Receive method will read the first enqueued datagram and return the data portion as a byte array. This method populates the remoteEP parameter with the IPAddress and port number of the sender.
If you want nonblocking behaviour you can use asynchronous version: UdpClient.BeginReceive method.
无需关闭窗口防火墙,只需将您的程序添加到“允许的程序”
例如,如果您的服务运行位置是“C:\Program Files (x86)\MyWork\Service1.exe”,
请转到防火墙,单击“允许程序或功能”通过窗口防火墙”从左上角。
单击“允许另一个程序”
单击“浏览”选择您的程序,例如 Service1.exe
点击“添加”
它将出现在您的“允许程序和功能列表”下。
Instead of turning off window firewall simple add your program to "Allowed Programs"
For example if your service running location is "C:\Program Files (x86)\MyWork\Service1.exe"
Go To firewall click on "Allow a program or feature through window firewall" from left top corner.
Click on "Allow Another Program"
Click on "Browse" select your program e.g. Service1.exe
Click on "Add"
it will appear under your "Allow programs and features list".