using IPC over local TCP to communicate from Client to a Server thread. The connection itself doesn't seem to be throwing any errors, but every time I try to make one of the associated calls, I get this message:
System.Runtime.Remoting.RemotingException: Could not connect to an IPC Port: The System cannot Find the file specified
What I am attempting to figure out is WHY. Because this WAS working correctly, until I transitioned the projects in question (yes, both) from .NET 3.5 to .NET 4.0.
Listen Code
private void ThreadListen()
{
_listenerThread = new Thread(Listen) {Name = "Listener Thread", Priority = ThreadPriority.AboveNormal};
_listenerThread.Start();
}
private void Listen()
{
_listener = new Listener(this);
LifetimeServices.LeaseTime = TimeSpan.FromDays(365);
IDictionary props = new Hashtable();
props["port"] = 63726;
props["name"] = "AGENT";
TcpChannel channel = new TcpChannel(props, null, null);
ChannelServices.RegisterChannel(channel, false);
RemotingServices.Marshal(_listener, "Agent");
Logger.WriteLog(new LogMessage(MethodBase.GetCurrentMethod().Name, "Now Listening for commands..."));
LogEvent("Now Listening for commands...");
}
Selected Client Code
private void InitializeAgent()
{
try
{
_agentController =
(IAgent)RemotingServices.Connect(typeof(IAgent), IPC_URL);
//Note: IPC_URL was originally "ipc://AGENT/AGENT"
// It has been changed to read "tcp://localhost:63726/Agent"
SetAgentPid();
}
catch (Exception ex)
{
HandleError("Unable to initialize the connected agent.", 3850244, ex);
}
}
//This is the method that throws the error
public override void LoadTimer()
{
// first check to see if we have already set the agent process id and set it if not
if (_agentPid < 0)
{
SetAgentPid();
}
try
{
TryStart();
var tries = 0;
while (tries < RUNCHECK_TRYCOUNT)
{
try
{
_agentController.ReloadSettings();//<---Error occurs here
return;
} catch (RemotingException)
{
Thread.Sleep(2000);
tries++;
if (tries == RUNCHECK_TRYCOUNT)
throw;
}
}
}
catch (Exception ex)
{
HandleError("Unable to reload the timer for the connected agent.", 3850243, ex);
}
}
If you need to see something I haven't shown, please ask, I'm pretty much flying blind here.
Edit: I think the issue is the IPC_URL String. It is currently set to "ipc://AGENT/AGENT". The thing is, I have no idea where that came from, why it worked before, or what might be stopping it from working now.
Update
I was able to get the IPC Calls working correctly by changing the IPC_URL String, but I still lack understanding of why what I did worked. Or rather, why the original code stopped working and I needed to change it in the first place.
The string I am using now is "tcp://localhost:63726/Agent"
Can anyone tell me, not why the new string works, I know that...but Why did the original string work before and why did updating the project target to .NET 4.0 break it?
Related
Using PKCS11Interop on Safenet HSMs, I got this error
"Method C_OpenSession returned 2147484548"
the error, in my documentation, is CKR_SMS_ERROR: "General error from secure messaging system - probably caused by HSM failure or network failure".
This confirm the problem it happens when the connectivity is lacking.
The problem is when this happens, the service isn't able to resume the communication when the connectivity is back, until I restart manually the service managing the HSM access.
When the service starts, I call this:
private Pkcs11 _pkcs11 = null;
private Slot _slot = null;
private Session _session = null;
public async void InitPkcs11()
{
try
{
_pkcs11 = new Pkcs11(pathCryptoki, Inter_Settings.AppType);
_slot = Inter_Helpers.GetUsableSlot(_pkcs11, nSlot);
_session = _slot.OpenSession(SessionType.ReadOnly);
_session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
}
catch (Exception e)
{
...
}
}
When I have to use the HSM, I call something like:
using (var LocalSession = _slot.OpenSession(SessionType.ReadOnly))
{
...
}
And, when I fail the communication due to a connectivity lack, I call a function to reset the connection and try to change the slot:
private bool switching = false;
public async void SwitchSlot()
{
try
{
if (!switching)
{
switching = true;
if (nSlot == 0)
{
nSlot = 2;
}
else
{
nSlot = 0;
}
_session.Logout();
_slot.CloseAllSessions();
_pkcs11.Dispose();
InitPkcs11();
switching = false;
}
}
catch (Exception e)
{
...
}
}
But, this last snippet doens't work as expected: it tries to change the slot, but it fails always to communicate with the HSM (after a network down). If I restart the service manually (when the connectivity is back), it works like charms. So, I'm sure I'm doing something wrong in the SwitchSlot function, when I try to close the _session and open a new one.
Do you see any errors/misunderstoonding here?
I have a C++ Windows service exposing a .Net Remoting interface for a local client to use and everything works great until the IP address changes.
Since I have to support .Net 2.0, switching to WCF isn't an option.
Any ideas on what I can do?
Here's how I set up the channel:
Hashtable^ dict = gcnew Hashtable();
dict["port"] = 9085;
dict["authenticationMode"] = "IdentifyCallers";
dict["impersonate"] = nullptr;
dict["secure"] = true;
dict["typeFilterLevel"] = "Full";
TcpServerChannel^ tcpChannel;
try
{
tcpChannel = gcnew TcpServerChannel( dict, nullptr);
}
catch (Exception^ e)
{
}
try
{
ChannelServices::RegisterChannel(tcpChannel, true);
}
catch (RemotingException^ RemoteException)
{
return FALSE;
}
catch (Exception^ e) { }
MyServiceProxy^ proxy = gcnew MyServiceProxy(m_pService);
RemotingServices::Marshal(proxy,"ServiceProxy");
Here's how I'm connecting to that service via C#
IDictionary dict = new Hashtable();
dict["port"] = 9085;
dict["name"] = "127.0.0.1";
dict["secure"] = true;
dict["tokenImpersonationLevel"] = "Impersonation";
dict["typeFilterLevel"] = "Full";
dict["connectionTimeout"] = 10000; // 10 seconds timeout
workChannel = new TcpClientChannel(dict, null);
try
{
ChannelServices.RegisterChannel(workChannel, true);
}
catch (System.Exception /*e*/)
{
}
string objectPath = "tcp://127.0.0.1:9085/ServiceProxy";
obj = (IMyService)Activator.GetObject(typeof(IMyService), objectPath);
I mean when the computers IP address changes. So here's the flow.
Start the service which sets up the channel, then close the laptop lid, go home, open it back up again, get assigned a new IP address, now when I try to start the client and it can't connect the the service.
After a good bit of research, I ran across the 'bindTo' parameter...and all I needed to do was to add the parameter to the TCPServerChannel dictionary.
dict["bindTo"]= "127.0.0.1";
If this didn't work, I was going to try to using the IPCServerChannel, but thankfully this one line was all I needed.
And to think, this one line has caused so much grief.
Thank you Alexei for helping.
I have two self hosted services running on the same network. The first is sampling an excel sheet (or other sources, but for the moment this is the one I'm using to test) and sending updates to a subscribed client.
The second connects as a client to instances of the first client, optionally evaluates some formula on these inputs and the broadcasts the originals or the results as updates to a subscribed client in the same manner as the first. All of this is happening over a tcp binding.
My problem is occuring when the second service attempts to subscribe to two of the first service's feeds at once, as it would do if a new calculation is using two or more for the first time. I keep getting TimeoutExceptions which appear to be occuring when the second feed is subscribed to. I put a breakpoint in the called method on the first server and stepping through it, it is able to fully complete and return true back up the call stack, which indicates that the problem might be some annoying intricacy of WCF
The first service is running on port 8081 and this is the method that gets called:
public virtual bool Subscribe(int fid)
{
try
{
if (fid > -1 && _fieldNames.LeftContains(fid))
{
String sessionID = OperationContext.Current.SessionId;
Action<Object, IUpdate> toSub = MakeSend(OperationContext.Current.GetCallbackChannel<ISubClient>(), sessionID);//Make a callback to the client's callback method to send the updates
if (!_callbackList.ContainsKey(fid))
_callbackList.Add(fid, new Dictionary<String, Action<Object, IUpdate>>());
_callbackList[fid][sessionID] = toSub;//add the callback method to the list of callback methods to call when this feed is updated
String field = GetItem(fid);//get the current stored value of that field
CheckChanged(fid, field);//add or update field, usually returns a bool if the value has changed but also updates the last value reference, used here to ensure there is a value to send
FireOne(toSub, this, MakeUpdate(fid, field));//sends an update so the subscribing service will have a first value
return true;
}
return false;
}
catch (Exception e)
{
Log(e);//report any errors before returning a failure
return false;
}
}
The second service is running on port 8082 and is failing in this method:
public int AddCalculation(string name, string input)
{
try
{
Calculation calc;
try
{
calc = new Calculation(_fieldNames, input, name);//Perform slow creation before locking - better wasted one thread than several blocked ones
}
catch (FormatException e)
{
throw Fault.MakeCalculationFault(e.Message);
}
lock (_calculations)
{
int id = nextID();
foreach (int fid in calc.Dependencies)
{
if (!_calculations.ContainsKey(fid))
{
lock (_fieldTracker)
{
DataRow row = _fieldTracker.Rows.Find(fid);
int uses = (int)(row[Uses]) + 1;//update uses of that feed
try
{
if (uses == 1){//if this is the first use of this field
SubServiceClient service = _services[(int)row[ServiceID]];//get the stored connection (as client) to that service
service.Subscribe((int)row[ServiceField]);//Failing here, but only on second call and not if subscribed to each seperately
}
}
catch (TimeoutException e)
{
Log(e);
throw Fault.MakeOperationFault(FaultType.NoItemFound, "Service could not be found");//can't be caught, if this timed out then outer connection timed out
}
_fieldTracker.Rows.Find(fid)[Uses] = uses;
}
}
}
return id;
}
}
catch (FormatException f)
{
Log(f.Message);
throw Fault.MakeOperationFault(FaultType.InvalidInput, f.Message);
}
}
The ports these are on could change but are never shared. The tcp binding used is set up in code with these settings:
_tcpbinding = new NetTcpBinding();
_tcpbinding.PortSharingEnabled = false;
_tcpbinding.Security.Mode = SecurityMode.None;
This is in a common library to ensure they both have the same set up, which is also a reason why it is declared in code.
I have already tried altering the Service Throttling Behavior for more concurrent calls but that didn't work. It's commented out for now since it didn't work but for reference here's what I tried:
ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 400,
MaxConcurrentSessions = 400,
MaxConcurrentInstances = 400
};
host.Description.Behaviors.RemoveAll<ServiceThrottlingBehavior>();
host.Description.Behaviors.Add(stb);
Has anyone had similar issues of methods working correctly but still timing out when sending back to the caller?
This was a difficult problem and from everything I could tell, it is an intricacy of WCF. It cannot handle one connection being reused very quickly in a loop.
It seems to lock up the socket connection, though trying to add GC.Collect() didn't free up whatever resources it was contesting.
In the end the only way I found to work was to create another connection to the same endpoint for each concurrent request and perform them on separate threads. Might not be the cleanest way but it was all that worked.
Something that might come in handy is that I used the svc trace viewer to monitor the WCF calls to try and track the problem, I found out how to use it from this article: http://www.codeproject.com/Articles/17258/Debugging-WCF-Apps
In my Windows 8 JS application, I have a web socket object defined like this:
var webSocket = new Windows.Networking.Sockets.MessageWebSocket();
webSocket.control.messageType = Windows.Networking.Sockets.SocketMessageType.utf8;
webSocket.onmessagereceived = that._onMessageReceived;
webSocket.onclosed = that._onClosed;
I connect using webSocket.connectAsync(uri).done(/* ... */) and that part works fine.
If I stop my web server on the other end, my application doesn't get notified and thinks the connection is still alive. The 'closed' event never fires, and there doesn't seem to be any 'Error' event.
Is there a way to monitor the connection status?
Figured it out. The messagereceived event actually fires when the connection fails. Inside the handler, you can use a try catch block around the data reader operation.
try {
var dataReader = args.getDataReader();
var msg = dataReader.readString(dataReader.unconsumedBufferLength);
} catch (ex) {
var error = Windows.Networking.Sockets.SocketError.getStatus(ex.number);
// do something
}
Is this a specific Windows 8 question? I've tested the following to work on Windows 7, OSX and Ubuntu (using reasonably new versions of Firefox, Safari and Chrome):
var s = new WebSocket("ws://"+window.location.hostname+":9876");
s.onopen = function(e) {
console.log("opened socket for unidrive log");
}
s.onclose = function(e) {
console.log("closed");
}
s.onmessage = function(e) {
console.log("got message: " + e.data);
}
The onclose event fires immediately if the web-server isn't running to start with, or fires on killing the server.
Thank you for this Information - really weird why the socket don't raise the closed-event, but it works great.
One more info for C# developers: to determine the correct exception-errorstatus you have to do call the WebSocketError.GetStatus(hresult) instead of the SocketError.GetStatus(hresult) method.
try
{
using (DataReader reader = e.GetDataReader())
{
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
string rawMessage = reader.ReadString(reader.UnconsumedBufferLength);
// Do something with the message...
}
}
catch (Exception ex)
{
var errorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.HResult);
if (errorStatus == WebErrorStatus.ConnectionAborted)
{
// Handle the connection-abort...
}
}
In C# ASP.NET 3.5 web application running on Windows Server 2003, I get the following error once in a while:
"Object reference not set to an instance of an object.: at System.Messaging.Interop.MessagePropertyVariants.Unlock()
at System.Messaging.Message.Unlock()
at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
at System.Messaging.MessageEnumerator.get_Current()
at System.Messaging.MessageQueue.GetAllMessages()".
The line of code that throws this error is:
Message[] msgs = Global.getOutputQueue(mode).GetAllMessages();
where Global.getOutputQueue(mode) gives the messagequeue I want to get messages from.
Update:
Global.getPool(mode).WaitOne();
commonClass.log(-1, "Acquired pool: " + mode, "Report ID: " + unique_report_id);
............../* some code /
..............
lock(getLock(mode))
{
bool yet_to_get = true;
int num_retry = 0;
do
{
try
{
msgs = Global.getOutputQueue(mode).GetAllMessages();
yet_to_get = false;
}
catch
{
Global.setOutputQueue(mode);
msgs = Global.getOutputQueue(mode).GetAllMessages();
yet_to_get = false;
}
++num_retry;
}
while (yet_to_get && num_retry < 2);
}
... / some code*/
....
finally
{
commonClass.log(-1, "Released pool: " + mode, "Report ID: " + unique_report_id);
Global.getPool(mode).Release();
}
Your description and this thread suggests a timing issue. I would create the MessageQueue object infrequently (maybe only once) and have Global.getOutputQueue(mode) return a cached version, seems likely to get around this.
EDIT: Further details suggest you have the opposite problem. I suggest encapsulating access to the message queue, catching this exception and recreating the queue if that exception occurs. So, replace the call to Global.getOutputQueue(mode).GetAllMessages() with something like this:
public void getAllOutputQueueMessages()
{
try
{
return queue_.GetAllMessages();
}
catch (Exception)
{
queue_ = OpenQueue();
return queue_.GetAllMessages();
}
}
You'll notice I did not preserve your mode functionality, but you get the idea. Of course, you have to duplicate this pattern for other calls you make to the queue, but only for the ones you make (not the whole queue interface).
This is an old thread, but google brought me here so I shall add my findings.
I agree with user: tallseth that this is a timing issue.
After the message queue is created it is not instantly available.
try
{
return _queue.GetAllMessages().Length;
}
catch (Exception)
{
System.Threading.Thread.Sleep(4000);
return _queue.GetAllMessages().Length;
}
try adding a pause if you catch an exception when accessing a queue which you know has been created.
On a related note
_logQueuePath = logQueuePath.StartsWith(#".\") ? logQueuePath : #".\" + logQueuePath;
_queue = new MessageQueue(_logQueuePath);
MessageQueue.Create(_logQueuePath);
bool exists = MessageQueue.Exists(_logQueuePath);
running the MessageQueue.Exists(string nameofQ); method immediately after creating the queue will return false. So be careful when calling code such as:
public void CreateQueue()
{
if (!MessageQueue.Exists(_logQueuePath))
{
MessageQueue.Create(_logQueuePath);
}
}
As it is likely to throw an exception stating that the queue you are trying to create already exists.
-edit: (Sorry I don't have the relevant link for this new info)
I read that a newly created MessageQueue will return false on MessageQueue.Exists(QueuePath)until it has received at least one message.
Keeping this and the earlier points i mentioned in mind has gotten my code running reliably.