TCP socket connection hangs on BGS5 | Telit Cinterion IoT Developer Community
February 2, 2015 - 1:15pm, 4296 views
Hello,
I have esperienced throuble using socket connection on BGS5.
My software hangs on any read or write operation when the TCP connection drops, for example, because signal stregth of GSM is too low.
Is there something wrong with my software?
Has anyone else experienced this same problem?
The firmware version used is:
ati1
Cinterion
BGS5
REVISION 01.100
A-REVISION 00.000.07
and the software I used for the test is the following:
package NetDemo;
import javax.microedition.midlet.*;
import java.io.*;
import javax.microedition.io.*;
public class NetDemo extends MIDlet implements Runnable {
static String destHost = "x.x.x.x";
static String destPort = "7";
static String connProfile = "bearer_type=gprs;access_point=ibox.tim.it;username=;password=";
SocketConnection sc = null;
InputStream is = null;
OutputStream os = null;
boolean Esci=false;
/**
* NetDemo - default constructor
*/
public NetDemo()
{
System.out.println("NetDemo: Constructor");
}
/**
* startApp()
*/
public void startApp() throws MIDletStateChangeException
{
System.out.println("NetDemo: startApp");
try
{
long t0=System.currentTimeMillis();
String openParm = "socket://" + destHost + ":" + destPort+ ";" + connProfile;
System.out.println("NetDemo: Connector open: " + openParm);
sc = (SocketConnection) Connector.open(openParm);
sc.setSocketOption(SocketConnection.LINGER,30);
is = sc.openInputStream();
os = sc.openOutputStream();
// Lancia il Thread di ricezione
Thread rxThread = new Thread(this);
rxThread.start();
System.out.println("Attesa ...");
// Attende fine thread
while(rxThread.isAlive()) {
Thread.sleep(5000);
System.out.println((System.currentTimeMillis()-t0)/1000+" secondi passati");
}
System.out.println("Chiudo ...");
Esci=true;
/* Close all */
is.close();
os.close();
sc.close();
}
catch (Exception e)
{
System.out.println("NetDemo: " + e.getMessage());
}
System.out.println("Fine app");
destroyApp(true);
}
/**
* pauseApp()
*/
public void pauseApp() {
System.out.println("NetDemo: pauseApp()");
}
/**
* destroyApp()
*
* This is important. It closes the app's RecordStore
* @param cond true if this is an unconditional destroy
* false if it is not
* currently ignored and treated as true
*/
public void destroyApp(boolean cond) {
System.out.println("NetDemo: destroyApp(" + cond + ")");
notifyDestroyed();
}
/**
* Thread ricezione
*/
public void run() {
byte[] buffer = new byte[256];
int n=0;
System.out.println("Inizio thread ricezione");
try {
os.write("Hello world".getBytes());
System.out.println("Attesa risposta...");
while ((n = is.read(buffer))>0)
{
String rx = new String(buffer,0,n);
System.out.println("Ricevuto:"+rx);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
System.out.println("Fine thread ricezione");
}
}
1. You could add the timeout parameter to the connection string given to Connector.open(). This is a network idle timeout. See the API for more information.
2. The underlaying socket does not have a configurable Timeout. So if the tcp socket connection is not ended nicelly, the BGS5 will not have received a FIN/RST packet and will timeout in about two hours if I'm right. To solve this you could use an extra Thread which closes the Stream AND connection after a timeout. After closing the connection the current, blocking, read will throw an IOException or InterruptedIOException.
I use a class which encapsulated an InputStream and its Connection and extends from InputStream to preserve the API. This class has a Timer which will be reset by every byte read. (In the read method). If the timer expires it closes the underlaying connection.
3. You could use a nonblocking socket. (use blocking=false)
Thank you very much for your reply
1. If i add timeout=*** to the connection string as if I use
sc.setSocketOption(SocketConnection.LINGER,30); seems nothing change about problem exposed.
2. The fact that the socket does not have a configurable time-out is a problem of the bgs5 module in particular or is a normal condition ? Anyway thanks for the tip on the workaround.
3. using non blocking socket do not completely resolve the issue, I have to check in any way if the socket is "alive" and operational or the connection is lost.
By the way i used blocking=false on the serial port and don't works, the read operation hangs in any case. Do you know if on tcp socketconnection the blocking parameter works ?
Hello,
2. It's generally a problem to detect the broken connection without sending data. If the other party did not close the connection gracefully we don't get any information about that.
3. According to API the InputStream read() method blocks until input data is available. If you use DataInputStream you can use the available() method to check if data is available. Blocking option for serial connection only means waiting for full buffer when reading.
Best regards,
Bartłomiej
1, The LINGER option has nothing to do regarding tcp timeouts.
I stronly suggest to use your own timeout mechanism.
I use to variants;
1. With a timer thread which closes the underlaying connection. (Composition of a InputStream)
2. Every call to int read() will get in to a while(available() == 0) loop which checks every time the current duration of which there is still no data. Throws an exception when the time out has expired.