Get Address Already In Use exception. self hosted wcf service - c#

I found numerous questions about this issue : here, here, here, and here, But could not solve my problem.
Background:
We have an existing unmanaged application that launches a managed winforms application.
There is a shared managed assembly which exposes comvisible objects for the unmanaged app and that assembly launches the managed app.
So the ServiceHost runs on the winforms app and the client on that shared assembly. The setup is similar to this implementation .
The application runs on a approx. 100 pcs, win xp or win 7.
The problem:
once in a few days we get :
System.ServiceModel.AddressAlreadyInUseException when trying to launch the winforms application.
we ran netstat but could not find anything listening on that port.
The only 'solution' is rebooting the pc.
I could not reproduce this problem on my dev machine. but it happens on production environment once in a while.
Code:
Code is being typed hopefully without typos, can not copy paste :
Service config (found in winform appconfig):
<system.ServiceModel>
.
.
<services>
<service name="MyService">
<endpoint address="net.tcp://localhost:4444" binding="netTcpBinding"
contract="IMyService"/>
</service>
</services>
.
.
<\system.ServiceModel>
Service
StartService() is called from mainform_Load
private static void StartService()
{
try
{
_serviceHost = new ServiceHost(typeof(MyService));
_serviceHost.Open();
}
catch(Exception ex)
{
LogError(ex);
ExitApp();
}
}
private static void ExitApp()
{
try
{
_serviceHost.Close();
}
catch(CommunicationException cex)
{
LogError(cex);
_serviceHost.Abort();
}
finally
{
Application.Exit();
}
}
Client
private static void CallMyService()
{
var channelFactory = new ChannelFactory<IMyService>("net.tcp://localhost:4444");
IMyService myChannel= channelFactory.CreateChannel();
bool error = true;
try
{
myChannel.PerformOperation();
((IClientChannel)myChannel).Close();
error = false;
}
finally
{
if (error)
{
((IClientChannel)myChannel).Abort();
}
}
}
I hope i am clear enough, thanks.

We solved this issue back in 2015, i am sharing the answer now:
Since the communication between the processes is on the same machine, we used NetNamedPipeBinding instead of NetTcpBinding and we got no more System.ServiceModel.AddressAlreadyInUseException exceptions.
The setup is like the following (actual code is a bit different):
Service :
private static void StartService()
{
try
{
string address = "net.pipe://localhost/MyApp/NamedPipeBindingHost";
_serviceHost = new ServiceHost(typeof(MyService));
NetNamedPipeBinding b = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
_serviceHost.Open();
b.OpenTimeout = TimeSpan.FromMinutes(2);
b.closeTimeout = TimeSpan.FromMinutes(1);
b.ReceiveTimeout = TimeSpan.FromMinutes(10);
_serviceHost.AddServiceEndpoint(typeOf(IMyService), b, address);
_serviceHost.Open();
}
catch(Exception ex)
{
LogError(ex);
ExitApp();
}
}
private static void ExitApp()
{
try
{
_serviceHost.Close();
}
catch(CommunicationException cex)
{
LogError(cex);
_serviceHost.Abort();
}
finally
{
Application.Exit();
}
}
Client :
private static void CallMyService()
{
string address = "net.pipe://localhost/MyApp/NamedPipeBindingHost";
EndpointAddress ep = new EndpointAddress(adress);
var channelFactory = new ChannelFactory<IMyService>(GetNamedPipeBindings(), ep);
IMyService myChannel= channelFactory.CreateChannel();
bool error = true;
try
{
myChannel.PerformOperation();
((IClientChannel)myChannel).Close();
error = false;
}
finally
{
if (error)
{
((IClientChannel)myChannel).Abort();
}
}
}
private NamedPipeBinding GetNamedPipeBindings()
{
NamedPipeBinding binding = new NamedPipeBinding (NetNamedPipeSecurityMode.None);
binding.OpenTimeout = TimeSpan.FromMinutes(2);
b.closeTimeout = TimeSpan.FromMinutes(1);
b.SendTimeout = TimeSpan.FromMinutes(10);
return binding;
}

Something I noticed that helped in my machine: somehow IIS Express generated multiple addresses with that same port when I was configuring the project, and tried to launch all of them during testing causing this failure.
The error would also appear via a popup from the IIS Express taskbar icon. I navigated to its config file ("User Documents\IISExpress\config\applicationhost.config"), removed all 'site' nodes that contained virtual directory bindings to those addresses, saved and re-tried again and it worked.
Hope this works for you?

Related

Self-Hosted SignalR service won't work (start)

I have SignalR server as Class Library Project and i referenced it in Console application (to simulate Windows service)
Here is code for SignalR
public void Start()
{
try
{
string url = #"http://*:8081";
using (WebApp.Start<Startup>(url))
{
Logger.Info(string.Format("Server running at {0}", url));
}
}
catch (Exception ex)
{
Logger.Exception(ex, "Signalr start");
}
Run = true;
Logger.Info("Starting Worker");
workerThread = new Thread(() =>
{
Worker();
});
workerThread.Start();
}
And here is Startup class
public class Startup
{
Microsoft.AspNet.SignalR.HubConfiguration hubconfiguration = null;
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
hubconfiguration = new HubConfiguration();
hubconfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubconfiguration);
}
}
So, it is in one thread, and worker is in another. That seems fine since i did it in other project where it works. Worker thread isn't problem, it's just empty loop, not related to server in any way.
Problem is that server seems to "stop" - when i look with Netstat, nobody is listening on port 8081. There is no exception, it just silently fails.
I referenced Owin.Cors (and Owin.Host.HttpListener) in console project that actually runs this server but as I said, server just stops.
When I try to connect, client says "connection actively refused" and Putty (telnet) also says "can't connect".
Where is the problem? In a nutshell, i have Class Library with SignalR server that is referenced in Console project that runs it but server just wont work.
[edit]
And there is code of Console app that starts service
static void Main(string[] args)
{
ServiceEngine Engine = new ServiceEngine();
Engine.Start();
Console.ReadKey();
Engine.Stop();
}
P.S. Sorry for my bad English.
Well, i solved it. Here was a problem:
public static void Start()
{
try
{
string url = #"http://127.0.0.1:8081";
WebApp.Start<Startup>(url);
Logger.Info(string.Format("Server running at {0}", url));
}
catch (Exception ex)
{
Logger.Exception(ex, "signalr start");
}
Run = true;
Logger.Info("Starting Worker");
workerThread = new Thread(() =>
{
Worker();
});
workerThread.Start();
}
As you can see, using statement was removed and now it works fine! Interesting note - you can also make Singleton implementation of this "Engine", and it will also work.
I got Solution after doing lot of R & D. And Its a Simple change related to Account and Access Rights.
Use LocalSystem Account instead of LocalService Account in Service Installer.
You can do this either from doing below change in design view of your service installer:
Properties of Service Process Installer -> Set Account to LocalSystem.
or by doing below change in in designer.cs file of your service installer:
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;

Windows service starts on Windows 7 but fails to start on Windows Server 2008 R2

I have created a wcf service which is deployed via a managed windows service. what the onstart() does is it creates and opens a tcp host for the wcf serice.
everything works fine in windows 7 but when I try to install the service in windows server 2008 R2 the service starts and then stops with the error that sometimes services stop when there is nothing to do. It is run under the network service account.
I cant find anything usefull in the windows logs.
I have tryed installing a dubug build and call debugger.launch() but its not working. I cant use remode debug because the the process does not stay open long enough for me to attach to it.
I really dont know what to do. Here is my code:
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
try
{
//if (!System.Diagnostics.EventLog.SourceExists("i2s CU Service (eng)"))
//{
// System.Diagnostics.EventLog.CreateEventSource("i2s CU Service", "Application");
//}
System.Diagnostics.EventLog.CreateEventSource("i2s CU Service", "Application");
}
catch (Exception)
{
//throw;
}
eventLog1.Source = "i2s CU Service";
eventLog1.Log = "Application";
if (serviceHost != null)
{
serviceHost.Close();
}
System.Configuration.AppSettingsReader reader = new System.Configuration.AppSettingsReader();
Uri tcpUri = null;
try
{
tcpUri = new Uri((string)reader.GetValue("Uri", typeof(string))); //net.tcp://localhost:8008/i2sServer
serviceHost = new ServiceHost(typeof(ConcurrentUsers), tcpUri);
// Create a binding that uses TCP and set the security mode to none.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.None;
// Add an endpoint to the service.
serviceHost.AddServiceEndpoint(typeof(IConcurrentUsers), b, "");
// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message, EventLogEntryType.Error);
}
if (serviceHost.State == CommunicationState.Opened)
{
eventLog1.WriteEntry("Service started.", EventLogEntryType.Information);
}
}
protected override void OnStop()
{
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
eventLog1.WriteEntry("Service stopped.", EventLogEntryType.Information);
}
this code as is works perfectly fine in windows 7 but I cant get it to run on win 2008 R2 server.
Thanks in advance
Refactor your application as a console application, and then run it on the desired environment to be able to debug it easily.
I'm sure that the problem will reveal itself once you run your console replica under the same user account that is assigned to your windows service

WCF Service is not hosted on the machine

I have implemented a simple chat console app and it worked well. When i tried to apply the same concept on GUI app. the service side when hosting , there is any error but if i use CMD command netstat -ao to show all ports , it is not exists.So when i run client app , there is an Exception (No connection could be made because the target machine actively refused). How can i solve these problem ?
Server
ServiceHost host;
using (host = new ServiceHost(typeof(Service), new Uri("net.tcp://localhost:4111")))
{
host.AddServiceEndpoint(typeof(IService), new NetTcpBinding(), "IService");
try
{
host.Open();
}
catch
{
}
}
Client
public bool Connect()
{
DuplexChannelFactory<IService> pipeFactory = new DuplexChannelFactory<IService>(new InstanceContext(this),
new NetTcpBinding(),
new EndpointAddress(AppConfiguration.GetValue(net.tcp://localhost:4111/IService"));
try
{
pipeProxy = pipeFactory.CreateChannel();
if (pipeProxy.Register())
{
return true;
}
}
catch
{
}
return false;
}
Assuming you are showing all your code.
You need to add a line after host.Open();, you could add Console.ReadLine();
This would get the program to stop from existing. What happens now is that the host opens, then the program exists, and the host gets closed/garbage collected.
I have solve it.
In GUI remove the (using) at defined new ServiceHost. Why i don't know but it works!!!
ServiceHost host;
host = new ServiceHost(typeof(Service), new Uri("net.tcp://localhost:4111"));

Email me if windows service stops

I want to be able to check if a certain service is running (say it had a Display name - ServiceA). I want my program to check say every 5 mins that the service is still running. If it is fine, it will loop and wait another 5 mins and then check again. If it finds that ServiceA has stopped I want the program to email me and say...ServiceA has stopped running. Below I have the code which I have done so far which is able to pull all the current services running and there actual display name back to the console. Anyone any ideas on the code/logic needed for what I need above?
namespace ServicesChecker
{
class Program
{
static void Main(string[] args)
{
ServiceController[] scServices;
scServices = ServiceController.GetServices();
Console.WriteLine("Services running on the local computer:");
foreach (ServiceController scTemp in scServices)
{
if (scTemp.Status == ServiceControllerStatus.Running)
{
Console.WriteLine();
Console.WriteLine(" Service : {0}", scTemp.ServiceName);
Console.WriteLine(" Display name: {0}", scTemp.DisplayName);
}
}
//Create a Pause....
Console.ReadLine();
}
}
}
Put every service's name in an array and check if your wanted name is running
List<string> arr = new List<string>();
foreach (ServiceController scTemp in scServices)
{
if (scTemp.Status == ServiceControllerStatus.Running)
{
arr.add(scTemp.ServiceName);
}
}
if (arr.Contains("YourWantedName")
{
// loop again
}
else
{
// send mail
}
There's no need to iterate over all services, if you know which one you're looking for: you can instantiate ServiceController with the service name.
As for sending an email: take a look at the System.Net.Mail.MailMessage class.
NB: You know that you can also just configure the service to trigger an action if it fails?
You will need to track the state of the service which will require some sort of storage. The simplest is probably an XML file that tracks the status of the service, maybe a schema like this
<services>
<service name="service1" last-check="12/21/2011 13:00:05" last-status="running" />
...
</services>
Your monitoring app, will wake up find the status of the services it is interested in, and check to see what that service's previous status was. If the status was running, but is currently stopped, send the email. If the service wasn't found add it to the list of services.
Persisting the status of the services to disk protects you in the case when your monitoring app goes down.
Heres an example of a service which does quite something similar. Should be simple to adapt it to your needs..
public partial class CrowdCodeService : ServiceBase
{
private Timer stateTimer;
private TimerCallback timerDelegate;
AutoResetEvent autoEvent = new AutoResetEvent(false);
public CrowdCodeService()
{
InitializeComponent();
}
int secondsDefault = 30;
int secondsIncrementError = 30;
int secondesMaximum = 600;
int seconds;
protected override void OnStart(string[] args)
{
Loggy.Add("Starting CrowdCodeService.");
timerDelegate = new TimerCallback(DoSomething);
seconds = secondsDefault;
stateTimer = new Timer(timerDelegate, autoEvent, 0, seconds * 1000);
}
static bool isRunning = false;
// The state object is necessary for a TimerCallback.
public void DoSomething(object stateObject)
{
if (CrowdCodeService.isRunning)
{
return;
}
CrowdCodeService.isRunning = true;
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
try
{
////// Do your work here
string cs = "Application";
EventLog elog = new EventLog();
if (!EventLog.SourceExists(cs))
{
EventLog.CreateEventSource(cs, cs);
}
elog.Source = cs;
elog.EnableRaisingEvents = true;
elog.WriteEntry("CrowdCodes Service Error:" + cmd.Message.ToString(), EventLogEntryType.Error, 991);
}
}
finally
{
CrowdCodeService.isRunning = false;
}
}
protected override void OnStop()
{
Loggy.Add("Stopped CrowdCodeService.");
stateTimer.Dispose();
}
}

ASP.NET UDP socket code works in development, but not in production on IIS

I have the following UDP broadcast listener running as a static component in a seperate thread on an ASP.NET web application. Why I would do this is really, unimportant, but the reason why this wont work when deployed baffles me. I do have several console applications sending UDP broadcasts, and I've coded tested and confirmed this thread and its code working when running under Visual Studio on the VS2005 development web server, but the moment that I compile the code and deploy it to another machine and run it under IIS - it stops working. Furthermore, it doesnt ERROR, it just doesn't work.
The log4net logging also seems to only work in the Init() method, but not the thread (which is weird). But I have added some File.AppendAllText's to the thread and it DOES seem to be executing, but as far as I can tell, it stops on the line byte[] received = mUdpClient.Receive(ref mGroupEP);
I've made sure the port is open and tested in a console app (which works), I've checked permissions, even made the default identity use the Local System user account, but still nothing. I've checked the firewall, checked the event log - nothing. No errors, just not working.
I wondered if it might be somehting to do with IIS shutting down System.Net requests as a security meassure, but I can't find anything that might support that hypothesis.
public class UDPBroadcastListener {
#region Members
private ILogger mLogger = NullLogger.Instance;
private readonly int mPort;
private UdpClient mUdpClient;
private IPEndPoint mGroupEP;
public event EventHandler<GenericEventArgs<byte[]>> Received;
private Thread mThread;
#endregion
public UDPBroadcastListener(int port) {
mPort = port;
}
public void Init() {
try {
Logger.WarnFormat("Setting up the UDP packet listener on port {0}", mPort);
mGroupEP = new IPEndPoint(IPAddress.Any, mPort);
mUdpClient = new UdpClient();
mUdpClient.EnableBroadcast = true;
mUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress,
true);
mUdpClient.Client.Bind(mGroupEP);
Logger.InfoFormat("Successfully bound the UDP packet listener to the the port.");
mThread = new Thread(UpdateThread);
mThread.IsBackground = true;
Logger.Info("Starting the background listener thread.");
mThread.Start();
Logger.InfoFormat("Background listener thread started ok.");
} catch (Exception e) {
Logger.Error(e.Message, e);
}
}
public void Close() {
if (mThread != null) {
mThread.Abort();
}
if (mUdpClient != null) {
mUdpClient.Close();
mUdpClient = null;
}
}
public Thread Thread {
get { return mThread; }
}
private void UpdateThread() {
Logger.Info("Listener thread started.");
while (true) {
try {
Logger.Info("Waiting for broadcast");
byte[] received = mUdpClient.Receive(ref mGroupEP);
Logger.InfoFormat("Received {0} bytes", received.Length);
OnReceived(received);
} catch (Exception ex) {
Logger.Error(ex.Message, ex);
}
}
}
protected void OnReceived(byte[] pData) {
EventHandler<GenericEventArgs<byte[]>> handler = Received;
if (handler != null) Received(this, new GenericEventArgs<byte[]>(pData));
}
public virtual ILogger Logger {
get { return mLogger; }
set { mLogger = value; }
}
#region Dispose
private bool mDisposed = false;
public void Dispose() {
if (mDisposed) return;
mDisposed = true;
Close();
}
~UDPBroadcastListener() {
Dispose();
}
#endregion
}
}
I am now getting extremely desperate. Please help. :(
You could try investigating with TCPView (It shows UDP as well) to see if anything shows up on the production server. Check out "Troubleshooting Windows Firewall settings", although this is for XP and I doubt your production server is XP, but it may be helpful anyway. See the netstat example.

Categories

Resources