I am using an asyncTask which runs for every 1 sec.
I must check a condition every 1 sec that the socket connection is available or not before asyncTask starts.
I used socket.isConnected() -> it always returning true.
How to do this.
Please help..
Once a connection is made, isConnected() will always return true.
To check if the connection is still avaialble, you can:
Use socket.getInputStream().Read(). This will block until either some data arrives or the connection closes in which case it will return -1. Otherwise it will return the received byte. If you use socket.setSoTimeout(t) and then call Read(), 3 things can happen:
a) The connection closes and Read() returns -1;
b) Some data arrives and Read() returns the read byte.
c) Read() will block for t miliseconds and throw SocketTimeoutException which means no data was received and the connection is okay.
If you want to ckeck the connection quickly, set the timeout to 1. If you set it to 0, it will block indefinitely which is the default.
Use socket.getInetAddress().isReachable(int timeout).
Its too late but it may help someone else all you need to do is just check for your socket if it is not null and then in case if it is not null just disconnect your socket else create new socket and connect that
if(socket != null)
{
socket.disconnect();
}
else
{
socket.createSocket();
socket.connect();
}
here create socket is method in which you can create your socket
Hope it may help someone.
public class CheckSocket extends AsyncTask<String,String,String>{
#Override
protected String doInBackground(String... strings) {
try {
socket = new Socket("192.168.15.101", 23);
} catch (IOException e) {
e.printStackTrace();
}
if(socket.isConnected()){
Log.d(TAG, "doInBackground: connected");
}else {
Log.d(TAG, "doInBackground: not connected");
}
return null;
}
}
Related
by running netstat on the server:
UNTIL A FEW DAYS AGO: I could see the connection being ESTABLISHED only for about a second, and then it would disappear from the list
NOW: it stays as ESTABLISHED for about 10 seconds, then it goes into FIN_WAIT1 and FIN_WAIT2
the Android code is the same, the server is still the same
is it possible that some kind of Android update might have changed things?
I can't really explain it.
I report the code below. The urlConnection.disconnect() gets executed, but the connection remains established on the server.
HttpURLConnection urlConnection = null;
System.setProperty("http.keepAlive", "false");
try {
URL url = new URL(stringUrl);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream instream = new BufferedInputStream(urlConnection.getInputStream());
...
instream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection!=null) {
urlConnection.disconnect();
}
}
The moment all data on input stream is consumed, the connection is released automatically and added to the connection pool. The underlying socket connection is not released, assuming the connection will be reused in near future. It is a good practice to call disconnect in finally block, as it takes care of connection release in case of exceptions.
Here is the implementation of read method of FixedLengthInputStream:
#Override public int read(byte[] buffer, int offset, int count) throws IOException {
Arrays.checkOffsetAndCount(buffer.length, offset, count);
checkNotClosed();
if (bytesRemaining == 0) {
return -1;
}
int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
if (read == -1) {
unexpectedEndOfInput(); // the server didn't supply the promised content length
throw new IOException("unexpected end of stream");
}
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
When bytesRemaining variable becomes 0, endOfInput is called which will futher call release method with true parameter, which will ensures the connection is pooled.
protected final void endOfInput(boolean reuseSocket) throws IOException {
if (cacheRequest != null) {
cacheBody.close();
}
httpEngine.release(reuseSocket);
}
Here is the release method implementation. The last if check ensures whether connection need to be closed down or added to the connection pool for reuse.
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
}
Note: I had previously answered couple of SO questions related to HttpURLConnection, which can help you in understanding the underlying implementation. Here are the links : Link1 and Link2.
As per how the TCP protocol works, when you close a connection, it doesn't automatically disappear from within your socket list.
When you send the termination signal to the other part, there starts a protocol (a procedure, morelike), where the first step is precisely your intention of closing the connection. You send a signal to the other node and that would involve the FIN_WAIT1 status.
When the user has received that signal, the next step is to acknowledge it from the remote side. This means that the opposite server sends you another signal symbolizing that the node is ready to close the connection too. That would be the FIN_WAIT2 status.
Between these two steps, it might happen that the remote node hasn't responded yet (so you're not been acknowledged that you want to close the connection). In that time, you would be in an intermediate state called CLOSE_WAIT (resuming: once you've sent the FIN signal to the remote server and they haven't responded yet).
The TIME_WAIT state would mean that you are giving some graceful time to the server before definitely closing it to receive some packets. You do this because connection anomalies might happen, and the remote server could have not received the 'disconnection' message and send you some packet. So when that happens, instead of creating a new socket between both nodes, you associate it to the one you have in the TIME_WAIT state and simply discard that packet because probably the sequence number will not be ordered.
There are some other states you might see, but according to the way you describe it, it seems pretty normal to me, unless when you call the .disconnect() method, the ESTABLISHED status would last. In that case something's not working as expected (it might be related to some kind of overloading or non-optimized code which might make your execution very slow).
You have to disconnect your open UrlConnection
HttpURLConnection urlConnection = null;
System.setProperty("http.keepAlive", "false");
try {
URL url = new URL(stringUrl);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream instream = new BufferedInputStream(urlConnection.getInputStream());
...
instream.close();
urlConnection.disconnect(); //HERE
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection!=null) {
urlConnection.disconnect();
}
}
I have created one android Bluetooth program which communicates with serial port. In my program I have 3 buttons: Connect, Select & Disconnect. Connect is used for enabling Bluetooth. Select is used for retrieving data from serial port. Disconnect is for disconnecting Bluetooth and the socket which I obtained to retrieve data, and to initialize the socket as null.
btnDisConnect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try{
mBluetoothAdapter.disable();
mmSocket.close();
mmSocket=null;
} catch(Exception e) {
Toast.makeText(getApplicationContext(), "Unable to Close.Try again", Toast.LENGTH_LONG).show();
}
}
});
My problem is when I tried to initialize the socket as null it shows Null Pointer exception.
I want to make this socket as null for further work. How can I make it null on buttonclick?
Please remember to close your Input/output streams first, then close the socket.
By closing the streams, you kick off the disconnect process. After you close the socket, the connection should be fully broken down.
If you close the socket before the streams, you may be bypassing certain shutdown steps, such as the (proper) closing of the physical layer connection.
Here's the method I use when its time to breakdown the connection.
/**
* Reset input and output streams and make sure socket is closed.
* This method will be used during shutdown() to ensure that the connection is properly closed during a shutdown.
* #return
*/
private void resetConnection() {
if (mBTInputStream != null) {
try {mBTInputStream.close();} catch (Exception e) {}
mBTInputStream = null;
}
if (mBTOutputStream != null) {
try {mBTOutputStream.close();} catch (Exception e) {}
mBTOutputStream = null;
}
if (mBTSocket != null) {
try {mBTSocket.close();} catch (Exception e) {}
mBTSocket = null;
}
}
So I have TCP server in Windows that is programmed in C++ and a client in JAVA, Android 4.0.4.
In Android, I connect like this:
public boolean sendConnectRequest()
{
while (isSocketConnected == false)
{
try {
if(comSocket == null)
comSocket = new Socket("192.168.0.1",1531);
isSocketConnected = comSocket.isConnected();
if (isSocketConnected) {
out = comSocket.getOutputStream();
in = comSocket.getInputStream();
}
else
comSocket.close();
}
catch (IOException ex)
{
Log.e("TCP Error", ex.getLocalizedMessage());
}
}
return true;
}
I typically have no problems with this code on the first connection to the server.
When i disconnect from the server, I call this:
public void closeConnection() {
if (comSocket != null)
{
try {
comSocket.close();
isSocketConnected = false;
if (out != null)
out.close();
if (in != null)
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So here is the problem... I hit the home button on the smartphone, which places the program in pause. I start the program again and it calls the resume function in activity, which in turn starts the process toward reconnection. The connection is attempted and i get no errors. However, my Windows server records no connection. In Windows, I know that I am still blocked at:
SOCKET connectionSocket = accept(tcpNetworkData->socket, (struct sockaddr*)&from, &fromlen);
I believe this is normal. When I am in debug mode on the Android side, I notice that it returns immediately from the line: comSocket = new Socket("192.168.0.1",1531); This should indicate to me that a connection is made.
If you follow me so far... I should also say that if I shut the server down, the client resets by closing the connection and opening a new one. This time the comSocket = new Socket("192.168.0.1",1531) does not block as it should and the execution keeps going. This is obviously wrong. I think it is a resource release problem but why? With Winsock you can solve this problem with this line of code:
int so_reuseaddr = TRUE;
setsockopt(networkData->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&so_reuseaddr,sizeof(so_reuseaddr));
Can you do something similar with Android or do you have to? Thank you for your help!
According to the javadoc the connection is established once you call the constructor.
Socket(InetAddress address, int port)
Creates a stream socket and connects it to the specified port number at the specified IP address.
When you press the home button, your app goes in background but it does not get killed immediately, so your comSocket might be not null when you get back to your application. In that case you are not calling the constructor again, thus you are not reconnecting to the server. What you should do is
if(comSocket == null){
comSocket = new Socket("192.168.0.1",1531);
}else{
comSocket.connect(new InetSocketAddress("192.168.0.1",1531));
}
(and please please place the curly brackets :-) )
Something to keep in mind is that the isConnected() method isn't very reliable for detecting when the remote side has closed the connection, (here is an example).
You have to figure this out by reading or writing on the associated Input/Output Streams.
Try using PrintWriter.checkError(), which will return true as soon as the client can no longer connect to the server.
I am having an issue where when I call sock.connect() it just hangs indefinitely. There is no exception and no timeout.
try
{
Method m = dev.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
sock = (BluetoothSocket) m.invoke(dev, 1);
sock.connect();
Thread.sleep(100);
in = sock.getInputStream();
out = sock.getOutputStream();
}
catch(ConnectTimeoutException ex)
{
return false;
}
catch(IOException ex)
{
return false;
}
catch(Exception ex)
{
return false;
}
The reason is that another app is using the bluetooth device already. I am trying to make my connection fail and at least throw an exception or something to let me know the device is already in use by another app.
Any other suggestions to approaching this?
Thanks.
Why are you calling Thread.Sleep? BluetoothSocket.connect is a blocking call. This means that your Thread.Sleep will not be called until connect returns with either a successful connection or throws an exception.
Are you calling this in an activity? As this will hang your activity. You should have 3 threads to handle bluetooth, an accept thread, connect thread and a connected thread. Like in the BluetoothChat example here:
http://developer.android.com/resources/samples/BluetoothChat/index.html
I need to have a "stable" connection to a server.
The client tries to connect to the server every 5 (10, N)-seconds.
After having connected successfully the client receives data from the server.
In case of service interruption (server shutdown, for example), go to step #1.
How I test:
I start the server
I start the client (to be sure that client gets data from the server)
I stop the server
I wait for about 200 client attempts to connect to the server.
I restart the server.
The server sends data, but the client doesn't get it.
socket.connect(...) is sucessfull, but
socket.getInputStream().read(byte[]) is not: the Thread blocks on input.read(..).
If I uncomment this line:
//socket.setSoTimeout(500);
then input.read(..) throws a TimeoutException.
But the server receives data from the client.
Where is my wrong?
Thanks.
Part of client code:
private void initSocket() {
try {
if (socket == null || socket.isClosed() == true
|| socket.isConnected() == false) {
socket = new Socket();
// socket.setSoTimeout(500);
InetSocketAddress socketAddress = new InetSocketAddress("192.168.1.3"
, 12344);
notifyDataListener(4);
socket.connect(socketAddress, 500);
notifyDataListener(5);
}
} catch (Throwable t) {
System.err.println(t);
}
}
private void closeSocket() {
try {
if (socket != null && socket.isClosed() == false) {
socket.close();
}
} catch (Throwable t) {
System.err.println(t);
}
}
private byte[] buffer = new byte[1024];
public void run() {
while (isActive) {
try {
notifyDataListener(1);
initSocket();
InputStream input = socket.getInputStream();
int length = input.read(buffer);
if (length < 0) {
throw new EOFException("Was got -1");
}
notifyDataListener(2);
} catch (Throwable t) {
closeSocket();
notifyDataListener(3);
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
}
}
}
}
On J2SE the same code works fine. Connection repairs after many wrong attempts.
It looks like Android has limit slosts of sockets (FileDescriptior?), takes them, but don't release after.
Your likely running out of file descriptors, i'm sure the limit is much lower on android than on a typical desktop configuration but the specific values will vary.
With the way you've coded this, the socket will hang around until its garbage collected, additionally on some platforms, the OS level sockets do not close instantly but hang around for a period of time to clean up any hanging data.
The first thing you should do is move your socket.close() code to finally {} statements which will free the socket immediately rather than waiting for garbage collection.