What steps will reproduce the problem? 1. Running the feedback service right after sending out the push notifications
- The feedback service works fine most of the time, but will get stuck once a while (like once every 30 or 40 times), at the line:
apnsStrean.AuthenticateAsClient(Host, certificates, System.Security.Authentication.Sslprotocols.Ss13, false);
in the ensureConnected() method of class FeedbackService.
- It will stuck at that line for 5 to 10 minutes and then throw an IOException which always says:
An existing connection was forcibly closed by the remote host...
After that, it comes back to work again.
What version of the product are you using? On what operating system?
I am using the latest version of the apns-sharp code running on Windows xp sp3 with visual studio 2010.
Please provide any additional information below.
The thing that confuses me most is that why does the apnsStream.AuthenticateAsClient() line work most of the time and suddenly stop working for a bit, and why does it take so much time to throw an exception? I guess there's something I don't understand here. This has driven me nuts, please point me out some directions. Thank you so much!!!
Comment #1
Posted on Jun 15, 2010 by Helpful DogTo be accurate, the IOException says:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
Comment #2
Posted on Jun 21, 2010 by Happy LionI'm not sure where to go with this one. I've never seen this myself, and there's nowhere I'm aware of that the timeout can be set on that method call.
Can you try some testing with the apnsStream.ReadTimeout and apnsStream.WriteTimeout ? Try setting them to an appropriately low value and see if that causes the exception to arise a bit more quickly.
Comment #3
Posted on Jun 21, 2010 by Massive GiraffeHi,
I am experiencing the same issue. Here are more details about the environment: I have installed a service that uses that library on a Widnows 2003 Server RC. I have not really been able to pinpoint when and why it occures but it happened on some notifications and some devices. To be more accurate some notifications can get to a device but the same notification may not be able to get to another one.
Here are some more technical details: the error that is occuring is a service error (the event .OnError is raised)
/* CODE STARTING */ service.Error += new NotificationService.OnError(service_Error); /**************/
I have intercepted that error to write a log into the server's event viewer :
/* CODE STARTING */ static void service_Error(object sender, Exception ex) { EventLog.WriteEntry("My Notifier Service - Error", String.Concat("Error: ", ex.Message, "\n\rInner exception: ", ex.InnerException, "\n\rSource:", ex.Source, "\n\rStack:", ex.StackTrace, "\n\rTargetSite (method):", ex.TargetSite), EventLogEntryType.Error); } /**************/
Here is the log in the event viewer when the errror occures :
/* LOG STARTING */ Error: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.
Inner exception: System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
Source:System
Stack: at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Security._SslStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.Write(Byte[] buffer) at JdSoft.Apple.Apns.Notifications.NotificationConnection.workerMethod()
TargetSite (method):Void Write(Byte[], Int32, Int32) /************/
Looking at the code file NotificationConnection.cs it looks like the error occures in the method workerMethod() at the line apnsStream.Write(buffer); . That code is protected by a try catch and it is here that the error is raised. It explains why we do not receive a notification faiulure (that code should be reached later in the function but it stops at the below try catch).
/* CODE STARTING */ try { //Send the notification apnsStream.Write(buffer); sent = true; //Can only assume it worked at this point } catch (Exception ex) { if (this.Error != null) this.Error(this, ex); } /**************/
If you need anymore information or anymore tests you can contact me on msn khazrak@hotmail.com . Can't wait to here from you...
Thank you, Vivien FRANCOIS - http://www.vivienfrancois.fr/
Comment #4
Posted on Jun 22, 2010 by Happy Lion@frvivi your issue is not identical. You're having problems with the .Write in your NotificationConnection.
Your network connection is being closed for some reason. One possibility is you are sending invalid notification data (eg: invalid device token). Hard to say. Does this happen on every notification for you?
It's pretty tough to diagnose this socketexception from my end. You're going to have to do some deeper digging to see if it's some other network issue on your server, or if you're sending bad notifications.
Comment #5
Posted on Jun 22, 2010 by Massive GiraffeHi jondick,
Thank you for the answer. It does not happen on every notification, it seems to be "random". Their should be another error for device token no ? (I log this error and it does not happen, not according to logs)
So according to you it is a connection that is closed during the Write method ?
Comment #6
Posted on Jun 22, 2010 by Happy LionWell the problem is, we don't necessarily no for sure that it's a bad device token, we can only guess.
Apple will close the connection on a bad device token, without any indication other than the closed connection, which we don't know for sure if it's a bad device token, or if the connection was lost due to other networking issues. So I hesitate to call all dropped connections a bad device token.
Make sense?
Comment #7
Posted on Jun 22, 2010 by Massive GiraffeYes indeed, it does make sense. What I meant is that their is this event that can be raised when the service encounters a bad device token :
/* CODE STARTING */ service.BadDeviceToken += new NotificationService.OnBadDeviceToken(service_BadDeviceToken);
[...]
static void service_BadDeviceToken(object sender, BadDeviceTokenException ex) { EventLog.WriteEntry("My Notifier Service - Wrong device token", String.Concat("Wrong device token: ", ex.Message), EventLogEntryType.Error);
endif
/**************/
So I thought in case their is a bad device token that log would have been created but it does not. So I will keep on investiguating that issue and verify if a bad device token can generate this. I will get back to you with the results.
Note: sorry if the subject of the post has derived, at the beginning I thought the issue we had was the same ;)
Best regards, Vivien FRANCOIS
Comment #8
Posted on Jun 22, 2010 by Happy LionSorry this event may be a bit deceiving... It's really only fired if you try using a device token that is obviously incorrect (eg: wrong # of characters).
I had originally thought about trying to detect when apple drops the connection right after sending a device token, and possibly assuming that was a bad device token, but at the end of the day, we just don't know for sure whether a connection dropped at that point means it's a bad device token. So, I'd rather have 0 false positives and error on the side of all dropped connections being just dropped connections.
Now, one other approach I could take a look at is detecting multiple disconnects for the same notification, and assuming a bad device token if that is the case. By default, the code will try sending the same notification multiple times (this is configurable of course), and eventually it will give up. So, let's say you set it to try sending the notification 5 times, if after 3 times, the message still isn't sent, and 3 disconnects are detected in that window of time, it's pretty safe to assume a bad device token (since we can check other problems with the notification before hand such as length of notification payload). I guess the trick to doing this would be to maintain all the various thresholds as configurable values... Maybe as simple as an additional property called BadDeviceTokenDisconnectionThreshold or something.
I'll give this some thought, but I don't think it's a really big issue, especially if you're checking the Feedback service regularly (say every hour or few hours). You really shouldn't end up with a lot of bad device tokens in normal operation.
One common cause for this behaviour is if you try and use sandbox/development device tokens against the production/adhoc/appstore push servers (and vice versa). So, make sure you're not doing that and you should see most issues related to this go away.
Comment #9
Posted on Jun 23, 2010 by Helpful DogHi jondick,
I added
apnsStream.WriteTimeout = 5000; apnsStream.ReadTimeout = 5000;
in front of the AuthenticateAsClient() line and it solved the problem. Before trying this, I used a timer to force the connection to close if when it got stuck for a while, and it worked too. However, I still don't understand what happened in there to cause this problem. This scenario happens when I kept sending a lot of notifications, so it's strange that I am the only one that has met this problem, or I guess there is something that I don't know of (which is probably the case...). But anyway, thanks a lot man!
Sterling
Comment #10
Posted on Jun 23, 2010 by Happy Lion@sterling.li maybe I'll add those timeouts to the code too so others don't run into this issue... Could be network related issue, hard to say, but as long as the timeout is low enough it should keep things running smoothly enough
Comment #11
Posted on Jul 5, 2011 by Massive BearHello All, I created push notification successfully, but about the feedback I'm not able to understand it? - when I'll get a feedback? - how to test feedback? - I tried JdSoft.Apple.Apns.Feedback.Test but I'm not getting any thing? - why service.Dispose() is in Main()? is this ok? I think it should be in .OnError or .OnFeedback event? - I have 3 iPhone for testing this, I deleted the app from one of them then I send a notification and it was ok for the other 2 but still no feedback?
Can any one create a sample project that have all features tested on it?
and what about JdSoft.Apple.AppStore what is that? and why the test project is not complete (in JdSoft.Apple.AppStore.Test there is event buttonOk_Click but there is no button with id buttonOk)?
Regards,
Status: Started
Labels:
Type-Defect
Priority-Medium
Code