Socket close timing - android

I have what appears to be a timing problem between a client (Galaxy Nexus) and a custom server since upgrading from Ice Cream Sandwich to Jelly Bean. Here is the general flow:
Client opens socket, issues HTTP get to server
Server accepts, starts new thread, responds with HTTP header and 200 OK.
Server writes (binary) file to socket.
Client reads data from socket and saves to a file.
After server thread writes all data, it closes the socket, and terminates
This has worked well over the past several months prior to the Jelly Bean update. Since the update the binary transfer succeeds about 70% of the time. The remaining 30% fails
when 'serverSocket.getInputStream().read' returns a -1 indicating the end of stream has been reached. No data has been read, no error exceptions raised, nothing in logcat.
The possibility of a timing problem arises when I change the server behavior in step #5. The thread was closing the socket after the write with the observed problems. If I remove the socket close, terminate the thread after the write, and let the OS eventually close the socket then it seems to work all the time.
I used tcpdump and WireShark to look at the packets in both the successful and failed cases. In the failed case a socket is closed in a few milli-seconds while in the successful case the socket is closed is a quarter or more of a second. The net of this is that any delay we cause in the socket closing improves our chances for success.
If anyone has any suggestions with what we may be doing to cause this problem or suggestions on how to narrow down the problem please feel free to respond. I can add code samples if required.

It looks like that when the server ask for the connection close, the socket is immediatly closed. Maybe the default ocket linger's time has changed between version ???
Try setting the socket linger's time using:
socket.setSoLinger(boolean on, int timeout);
to have the server waiting some time before close channel if some data still waiting to be sent.
If this doesn't solve, you can change your flow above to:
...
4.Client reads data from socket and saves to a file.
5.Client send confirmation to server.
6.Server close connection.
--EDITED--
A gracefull way to achive the above without additional TCP data packets traveling for the closing confirmation is:
when server finish writing to the socket calls:
socket.shutdownOutput();
when client socket.read() returns -1, client calls:
socket.close();
This ensures that client is informed that all data has been sent, and sender will wait for the socket closure protocol to complete.

Related

How can i disconnect in SignalR as my Mobile Data Connections gets off

I had implemented ASP.NET SignalR with Android App. App works great but there is a problem. when i off the data connections, It takes time SignalR to disconnect the connection id created while onConnected() because it try to make connections till the time reach up to disconnection time it try to keep making connections, as a result the period of approx 1.5 min the app become useless. which i don't want. I want if a connection gets break due to loss of connection should be disconnected immediately. Has anyone a solution for that.
You should create your own method to stop the clients connection on such an event. You would probably use something similar to this
connection.hub.stop();
But if you really want the server to not wait you'll adjust the disconnect timeout, but if you do you'll have to adjust the keep-alive timeout accordingly if that was set manually.
DisconnectTimeout
www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events#disconnecttimeout
This setting represents the amount of time to wait after a transport connection is lost before raising the Disconnected event. The default value is 30 seconds. When you set DisconnectTimeout, KeepAlive is automatically set to 1/3 of the DisconnectTimeout value.
// Wait a maximum of 30 seconds after a transport connection is lost
// before raising the Disconnected event to terminate the SignalR connection.
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30);

SMTPTransport sendMessage stuck on connection loss

i am using javamail's SMTPTransport.sendMessage method to send emails in my android app and everything works fine... but when i start sending a message and in the middle, i disable my wifi, it gets stuck. I have waited for more than 1hour now and it is still stuck; no exception is thrown... any idea how to handle this situation?
edit:
i have added a timeout
props.put("mail.smtp.connectiontimeout", "3000");
props.put("mail.smtp.timeout", "3000");
does not seem to work ... i have simulated a connection loss and it's already 5mins now and it is still in sending state and has not timed out
edit2:
timeout/error(not even sure if it is a timeout) occurred after 16mins
06-30 18:47:27.722: I/System.out(15906): javax.net.ssl.SSLException: Write error: ssl=0xdf8268: I/O error during system call, Invalid argument
edit 3:
it does not always throw an exception... i have simulated a connection loss and after 1hr, still no exception... it is in sending state..... and have not return yet :(
The current version of JavaMail only handles timeouts for reads, because that's all the JDK supports. For the next JavaMail release I've added support for write timeouts. You can experiment with it using the 1.5.1-SNAPSHOT release of JavaMail available in the maven.java.net repository. You'll need to set the "mail.smtp.writetimeout" property. Don't know if this will help you on Android since it's not really Java...

Getting "SocketException : Connection reset by peer" in Android

My app needs to contact the same device it is working on, via http://127.0.0.1/... (a localhost url).
For some reason, about 50% of the times (and maybe exactly 50%) when I reach a website there with JSON content, I get the exception:
java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
For the other 50%, I get perfectly good results. I've tried to do polls (and even large delay between polls), but I keep getting the same weird results.
I've searched the internet and also here, and I'm not sure why it occurs. Does the peer mean that the client has caused it? Why does it happen, and how should i handle it?
Some websites say that it's a common thing, but I didn't find what's the best thing to do in such cases.
Ok, the answer was that it's the server's fault - it had to close the connection after each request.
It might be that Android keeps a pool of connections and use the old one or something like that.
Anyway , now it works.
EDIT: according to the API of HttpURLConnection, this can be solved on the client side too:
The input and output streams returned by this class are not buffered.
Most callers should wrap the returned streams with BufferedInputStream
or BufferedOutputStream. Callers that do only bulk reads or writes may
omit buffering. When transferring large amounts of data to or from a
server, use streams to limit how much data is in memory at once.
Unless you need the entire body to be in memory at once, process it as
a stream (rather than storing the complete body as a single byte array
or string).
To reduce latency, this class may reuse the same underlying Socket for
multiple request/response pairs. As a result, HTTP connections may be
held open longer than necessary. Calls to disconnect() may return the
socket to a pool of connected sockets. This behavior can be disabled
by setting the http.keepAlive system property to false before issuing
any HTTP requests. The http.maxConnections property may be used to
control how many idle connections to each server will be held.
Taken from:
developer.android.com/reference/java/net/HttpURLConnection.html
Try to set this property for your HttpURLConnection before connecting:
conn.setRequestProperty("connection", "close");
This will disable "keep-alive" property which is on by default.
This is an old thread i know. But this might help someone.
In my case this error was caused by the .NET WCF (soap) service. One of the objects in the returning result had a DataMember with get{} property but no set{} property.
For serialization to occur every DataMember should have both get{} & set{} available. I implemented an empty set{} (empty due to my business rules), and problem was solved.
My scenerio is a specific bad server implementation, but maybe it'll help someone saving time when troubleshooting.
I was having a lot of these Connection reset by peer when I was visiting certain web pages or downloading files (from my app or the Android browser).
Turned out it was my 3G carrier that blocked the connections (e.g. downloading an .exe file was forbidden).
Do you have the same problem on Wifi ?
in my situation the problem has been solved by cleaning the proxy address and port from APN which was produced by the operator.
as I have tested, using IP address of remote server instead of domain name also can solve the problem.
In our case the issue is in the Server side (Application Pool configuration in IIS). I resolved it by setting Maximum Worker Processes to 1. Setting it with value more than 1 will enable Web Garden which seems to be the issue.

HTTP setReadTimeOut can work if Network Not Available after posting data to server and waiting for responce from server

I was Posting Data from Android Mobile to Server over HTTP connection. I was able to POST data to server and also get acknowledgement from Server. But sometime if my server communication thread waiting for acknowledgement from server after posting data that time i loss Internet Connectivity and thread unable to receive Ack from server and goes in infinite loop. I tried setReadTimeOut(180000) method.
Can it work for me? Can it gives SocketTimeOutException if no network Available/ No connection between server and mobile
Setting a timeout will most likely work. However, I would not recommend setting it to 180000 (= 180 seconds = 3 minutes!). 30 seconds is usually more than enough. You also might want to add a setConnectTimeout
Note that there are some situations where an HttpUrlConnection doesn't always work properly:
Android versions 2.2 or earlier, better use the Apache HTTP client for these versions (see also this post)
On the emulator (see also this post)

How to prevent the phone from losing IP traffic?

I have a simple app that periodically sends HTTP_GET requests to a server. When sending requests over 3G, I noticed that the requests sometimes time out (and the server-side logging shows that it NEVER receives the request either).
After trying out different combinations I found one consistant pattern when this problem occures (it times out after every 5-15 successful requests).
- TelephonyRegistry: notifyDataConnection() state=2isDataConnectivityPossible()true, reason=null
- TelephonyRegistry: broadcastDataConnectionStateChanged() state=CONNECTEDtypes=default supl, interfaceName=rmnet0
- NetworkLocationProvider: onDataConnectionStateChanged 3
According to Google, NetworkLocationProvider is changed to 'DATA_SUSPENDED', which implies "connection is up, but IP traffic is temporarily unavailable". (see TelephonyManager). On the situations where HTTP_GET requests succeeds, the state is changed to '8'. My app doesn't use the location manage and I've shut down every other non-critical app from running!
I want to know:
What is the cause of this issue? Why does the connection status go to DATA_SUSPENDED?
Is it possible to avoid/overcome this problem?
Any help/insight into this is much appreciated! Thanks in advance!
I have the same problem with my app running on an Huawei IDEOS X3 with Android 2.3.5. The app sends data each minute to a server using HttpClient.
Using logcat I can see that the data connection is lost and then reestablished after a short while. Previously my app stopped working since it tried to send data without a connection causing an exception which was not properly handed.
I don't know the reason for the intermittently dropped data connection but I now handle the situation by checking if there is a data connection prior to sending the data. In my case it does not matter if some data is never sent. If it was important to avoid data loss, I could buffer the data and send it once the connection was back.
public Boolean isDataConnection() {
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
return tm.getDataState() == TelephonyManager.DATA_CONNECTED;
}

Categories

Resources