问题
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();
}
}
回答1:
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.
回答2:
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.
回答3:
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".
来源:https://stackoverflow.com/questions/2298815/udpclient-receive-method-not-working-in-a-service