I've read here: Error 10048 when trying to open TcpChannel
I am having what I thought to be a similar problem - apparently not. I took the advice of the first respondant to reset winsock (how does the winsock get corrupted, anyhow?) Anyway, here is my channel registration:
channel = new TcpChannel(channelPort);
ChannelServices.RegisterChannel(channel, false);
and the client call:
// Create a channel for communicating w/ the remote object
// Notice no port is specified on the client
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel, false);
// Create an instance of the remote object
CommonDataObject obj = Activator.GetObject( typeof(CommonDataObject) ,
"tcp://localhost:49500/CommonDataObject") as CommonDataObject;
This seems all too straightforward to be such a hassle to use. But, the problem seems to be with the server's ChannelServices.RegisterChannel(...). Now, the reason I included the client portion is because the client instances, checks for the server object. If it can't find it, then it 'nudges' the server to instance itself. What I was wondering is if checking for the object's available first (a la: Activator.GetObject(...) ) would cause the ChannelServices to 'think' this tcp channel is already registered? It sounds dumb, but that is my only possible explanation. I have turned off the firewall, anti-fungal app, and rebooted. Still receive this
The channel 'tcp' is already
registered.
I looked at my stack trace and did notice:
at System.Runtime.Remoting.Channels.ChannelServices.RegisterChannelInternal(IChannel chnl, Boolean ensureSecurity)
at System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(IChannel chnl, Boolean ensureSecurity)
I wondered if the RegisterChannelInternal(...) might be what is causing the 'already registerd' issue. So, other than that, I am at a loss...
It's possible that the call I'm making to check for that Channel is causing it. If that is the consensus, then my question changes to: How can I poll for the Channel?
UPDATE:
After removing the initial check for the server from the client and 'assuming' that the server needs to be instanced, I did discover that the client checking is causing the problem. I've managed to get the server going, and the client did get a 'transparent proxy' object. But the question still remains: "How can I poll to discover if the server is instanced?"
The answer is evidently, yes...when the client is registering the channel, it keeps the server from registering another Tcp channel. I have removed the client instancing of a Tcp channel and the registration.
Since I haven't gotten an answer on pinging, I'm going through with a try/catch block on the obj = Activator.GetObject(...). If obj is returned null, then I 'nudge' the server, it fires up...and then the client connects with the CommonDataObject (derived from MarshalByRefObject).
So, in a sense, that is the polling technique I'm using. I'd like something more elegant - that is, an implementation that didn't work by causing a failure. To me, that's more of a hack work-around than a solution.
I found the answer here. Thanks to Abhijeet for the inadvertent solution!!! Btw...don't forget to declare:
using System.Linq;
Related
I'm using TcpListener to accept & read from TcpClient.
The problem is that when reading from a TcpClient, TcpClient.BeginRead / TcpClient.EndRead doesn't throw exception when the internet is disconnected. It throws exception only if client's process is ended or connection is closed by server or client.
The system generally has no chance to know that connection is broken. The only reliable way to know this is to attempt to send something. When you do this, the packet is sent, then lost or bounced and your system knows that connection is no longer available, and reports the problem back to you by error code or exception (depending on environment). Reading is usually not enough cause reading only checks the state of input buffer, and doesn't send the packet to the remote side.
As far as I know, low level sockets doesn't notify you in such cases. You should provide your own time out implementation or ping the server periodically.
If you want to know about when the network status changes you can subscribe to the System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged event. This is not specific to the internet, just the local network.
EDIT
Sorry, I misunderstood. The concept of "connected" really doesn't exist the more you think about it. This post does a great job of going into more details about that. There is a Connected property on the TcpClient but MSDN says (emphasis mine):
Because the Connected property only
reflects the state of the connection
as of the most recent operation, you
should attempt to send or receive a
message to determine the current
state. After the message send fails,
this property no longer returns true.
Note that this behavior is by design.
You cannot reliably test the state of
the connection because, in the time
between the test and a send/receive,
the connection could have been lost.
Your code should assume the socket is
connected, and gracefully handle
failed transmissions.
Basically the only way to check for a client connection it to try to send data. If it goes through, you're connected. If it fails, you're not.
I don't think you'd want BeginRead and EndRead throwing exceptions as these should be use in multi threaded scenarios.
You probably need to implement some other mechanism to respond to the dropping of a connection.
I'm using C#, and while working on a sending mail routine using the tools available on the .NET Framework and I've sumbled upon two situations
One mail server that requires SSL
One mail server that doesn't support SSL
So when using a generic mail sending tool, I've noticed that I should ask the user if SSL should be used, or figure it by coding.
When I try to send an E-Mail not using SSL through a mail server that requires it, I get an exception.
When I try to send an E-Mail using SSL through a mail server that doesnt support it, I get an exception.
By doing this, it should be easy to check wether I should use it or not.
But I want a smarter way to do this. I didn't find any way to do so. Is there one ?
Personally, I do not believe that your code should be "Automagically" determining if SSL should be used.
When the e-mail service is configured by the users, they should be telling you how it works and what is needed.
You can see this behavior by the way the out of the box .NET SMTP which you must tell it how it is.
To further this, some services have a different URL for SSL and non SSL, and maybe users SHOULD be using SSL, but you could let them accidentally send the wrong way.
bool supportsSSL = true;
Stream stream = new SslStream(client.GetStream(), false);
try
{
((SslStream)stream).AuthenticateAsClient("pop3.xyz.com");
}
catch (Exception e)
{
supportsSSL =false;
}
It sounds like you have the answer. As long as the SMTP library you are using does the right thing when throwing the exception, try ssl first, then fallback to non-ssl, and handle that error case (i.e. total failure) if it happens.
I think you are concerned because you don't know what's going on under the covers when the exception is thrown, and if that's so, I feel the same. I don't know if your .net toolkit provides the facilities, but you should be able to make the connection with a lower-level type connection object which allows you to test whether or not it's possible to make an ssl connection and check the return value of your attempt, then decide how to proceed based on that.
It may be more trouble than it's worth though, because you might then need to bolt on SMTP functionality to your new connection type, if your SMTP library doesn't support using an already established connection. Which is the long way around saying, you're probably doing well enough with catching the exception and trying again.
In reference to #Mitchel's answer, I'd say it's perfectly okay if it's automagic as long as the right notification is made, and of course the context is right. SMTP is still pretty often plain text, so any expectation of encryption for email is pretty low. Login credentials are another matter. If this is an app an end user would use, you certainly ought to make sure they're connecting over SSL if credentials will be exchanged.
I can't reconnect to MQQueueManager after a while as an exception (reason code 2059 - MQRC_Q_MGR_NOT_AVAILABLE) is thrown when I'm constructing new object of MQQueueManager. My client app is written in .NET/C# and I'm running it on Win2003.
However I can connect to QM after I have restarted my client app. This would indicate that some state is incorrect in QM libraries? How can I reset the state in code so that I could reconnect to QM? Is there a way to reset/disconnect all active TCP connections to QM from client app code?
My connection code:
Hashtable properties = new Hashtable();
properties.Add( MQC.HOST_NAME_PROPERTY, Host );
properties.Add( MQC.PORT_PROPERTY, Port );
properties.Add( MQC.USER_ID_PROPERTY, UserId );
properties.Add( MQC.PASSWORD_PROPERTY, Password );
properties.Add( MQC.CHANNEL_PROPERTY, ChannelName );
properties.Add( MQC.TRANSPORT_PROPERTY, TransportType );
// Following line throws an exception randomly
MQQueueManager queueManager = new MQQueueManager( qmName, properties );
Stack trace:
Source: amqmdnet
CompletionCode: 2
ReasonCode: 2059
Reason: 2059
Stack Trace:
at IBM.WMQ.MQBase.throwNewMQException()
at IBM.WMQ.MQQueueManager.Connect(String queueManagerName)
at IBM.WMQ.MQQueueManager..ctor(String qmName, Hashtable properties)
at WebSphereMQOutboundAdapter.WebSphereMQOutbound.ConnectToWebSphereMQ()
Connections are per-thread so if you are attempting to create a new connection while the previous QMgr object is still instantiated, you would get this. If you close the previous connection and destroy the object before creating a new object you should be OK. Since queues and other WMQ objects depend on a connection handle these will also need to be destroyed and then reinstantiated after the new connection is made.
There are of course a few other explanations for this behavior but these are much less likely. For example, it is possible that a channel exit or (in WMQ v7) configuration could be limiting the number of simultaneous connections from a given IP address. When a connection is severed rather than closed, the channel agent holding the connection on the QMgr side has to time out before the QMgr sees the connection as closed. If connection limiting is in place, these "ghost" connections reduce the available pool. But as I said, this is far less common than programs not cleaning up old objects prior to a reconnect attempt.
There is also the possibility that this is a bug. To reduce that possibility, and for a variety of other reasons such as WMQ v6 going end of life next year, I'd recommend use of WMQ v7.0.1.2 for this project, at both the client and server side. In general, you can use v7.0.1.2 client with a v6.0.x server as long as you stick to v6 functionality. Among other things, .Net code is better integrated in v7 and the Cat-3 SupportPacs are now included in the base install media rather than a separate download.
After some months fighting with this issue and IBM support, the best solution I found is to change the connect/disconnect code in IBM MQ Driver.
Instead of calling manager.Disconnect() and manager.Close() for each GET/PUT, connect once and then reconnect only if you have some exception (like loosing connection).
What I've figure out is that some bug exists in IBM MQ Driver that caches some information for each connect/disconnect. When this buffer is full, the application stops reconnecting.
The driver version (client DLL's) I have this issue is: 7.0.1.6
In my ASP.NET application, I have a line in the global application start event that configures the client remoting channel by calling RemotingConfiguration.Configure().
This works well the first time, but when my web application gets recycled, the application start event is fired again causing the following remoting exception:
Remoting configuration failed with the exception 'System.Runtime.Remoting.RemotingException: The channel 'tcp' is already registered.
I would like to detect if the channel is already configured so that I can avoid getting this exception.
Try ChannelServices.RegisteredChannels
http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.channelservices.registeredchannels(VS.71).aspx
I've been having this problem too.
The trouble is that you can stop the application that called RemotingConfiguration.Configure() but that doesn't make the channel available. Its something to do with ports or it might just be the name of the channel, I'm not sure.
The solution I found which seems to work is to get the registered channels and unregister the channel you want to remove.
Here is some code
RemotingConfiguration.Configure(appConfig, false);
// do this to unregister the channel
IChannel[] regChannels = ChannelServices.RegisteredChannels;
IChannel channel = (IChannel)ChannelServices.GetChannel(regChannels[0].ChannelName);
ChannelServices.UnregisterChannel(channel);
RemotingConfiguration.Configure(appConfig, false); // this is just a test to see if we get an error
I hope this works for you, it has for me
But what would you do if you found it was already registered?
In any case, I just wanted to make sure you knew that .NET Remoting has been deprecated in favor of WCF.
The TIBCO EMS user's guide (pg 292) says:
The backup server will work indefinitely to either A) become the
primary server or B) reconnect to the primary server. It also says
clients may receive fail-over notification when the switch is successful (see also TIBCO EMS .NET reference pg 220).
I have some questions spinning off of these facts...
What kind of errors occur on the client side while the servers are attempting fail-over/reconnect?
What is the appropriate response from the client?
Get new Connection objects from the ConnectionFactory until one works?
Wait for fail-over notification? (are current Connection instances fixed at this time? or do I need to get a new instance?)
I hope the scenario is clear, any related information or advice would be appreciated too.
I can at least answer #1 above.
If you have enabled Tibems.SetExceptionOnFTSwitch(true); and have set up an exception handler to capture the messages the server sends to the client, you will see the following:
For single-server, non-fault tolerant connection failures:
"Connection has been terminated".
For fault-tolerant connection failures:
"Connection has performed fault-tolerant switch to "
If you attempt to publish while the connection is down, a TIBCO.EMS.IllegalStateException is thrown with the "Producer is closed" message.
for #2 above, I think the answer is to allow the EMS library to handle as much as possible. Once we got the EMS reconnect functionality to work, it gracefully tried to reconnect until the server became available again and once it reconnected, it was like there was never a problem. The only gotcha is probably if you try to publish a message before the ems connection is back. This is where the exception handler comes in, Once notified that you are in failover mode, you can adjust exception handling on the publisher side to suppress the error until the connection is back. The thing I don't know is how do you tell when you've exhausted all reconnect attempts.
Anyway, Seems like our two worlds are closely related when it comes to EMS - hope our findings (based on your comments on my questions) help you.
We use TEMS (Tibco EMS - a Tibco Product for WCF) So it becomes a custom binding. We tried to break it by doing things like bounce the server to force switch overs and it works really well. make sure you are using version 1.2 not 1.1 because you cannot do anything other then client acknowledgement.