It seems to me that there is some kind of limitation in socket creation in MIDP.
I need to make lots of connections to a server (none concourrent) and in the forth or fith try my app crashes. It crashes in the simulator and in my real device as well.
To isolate any possibility of it being influenced by my code, I isolated the following code:
try {
StreamConnection c;
StringBuffer sb = new StringBuffer();
c = (StreamConnection) Connector.open(
"http://www.cnn.com.br/", Connector.READ_WRITE);
InputStreamReader r = new InputStreamReader(c.openInputStream(), "UTF-8");
System.out.println(r.read());
c.close();
} catch (IOException ex) {
ex.printStackTrace();
}
This code crashes in the 13th try.
I've tryed to add a sleep of 10 seconds inside a while loop and, it crashes at the 13th try too.
The crash message is:
java.io.IOException: Resource limit exceeded for TCP client sockets
- com.sun.midp.io.j2me.socket.Protocol.open0(), bci=0
- com.sun.midp.io.j2me.socket.Protocol.connect(), bci=124
- com.sun.midp.io.j2me.socket.Protocol.open(), bci=125
While c.close() inside the try should be adequate, I am wondering if you have other issues that are triggering this. The code really should be closing the connection AND inputstream inside of a finally. Something like this:
StreamConnection c = null;
InputStream is = null;
try {
StringBuffer sb = new StringBuffer();
c = (StreamConnection) Connector.open(
"http://www.cnn.com.br/", Connector.READ_WRITE);
is = c.openInputStream();
InputStreamReader r = new InputStreamReader(is, "UTF-8");
System.out.println(r.read());
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
System.out.println("Failed to close is!");
}
}
if (c != null) {
try {
c.close();
} catch (Exception ex) {
System.out.println("Failed to close conn!");
}
}
}
The reason, why the c.close() did not actually close was because the inputstream was not closed. Some devices require that both the stream and the connection be closed. Also the connections do not close immediately, on some devices, when the close() method is called. You might have to do a gc too
Related
public void lock() {
if (this.isLocked()) return;
try {
this.dataOut.flush();
this.dataOut.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(
this.byteOut.toByteArray())));
IntStream.Builder intStreamBuilder = IntStream.builder();
try {
try {
while (true) {
intStreamBuilder.accept(inputStream.readInt());
}
} catch (EOFException e) {
// logic to be executed after stream has been fully read
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
} finally {
inputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
What I do here is take an DataOutputStream containing Integers, flush its remaining contents into a ByteArrayOutputStream named this.byteOut and then build an IntStream from it.
I'm from the C# domain and in the process of learning Java, so the code here does not have any actual purpose.
Is there any way to do what I do here more elegantly in Java?
My two main concerns are:
The way I determine that the DataInputStream has been fully read is by catching an EOFException and putting the logic to be executed after reading inside a catch block. I don't like that, since I suppose throwing and catching exceptions is somewhat expensive? Is there a better way to determine that the stream doesn't contain any more Integers?
The fact that I have to wrap a try-catch block around a try-catch block just to be able to call inputStream.close() in the inner finally block. Is there a solution that is not so clunky?
It's mostly you.
If you don't like the try with resources construct,
you can still combine all of your try statments and stack the catch blocks.
public void lock()
{
DataInputStream inputStream = null;
IntStream.Builder intStreamBuilder;
if (isLocked())
{
return;
}
try
{
inputStream = new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(
byteOut.toByteArray())));
intStreamBuilder = IntStream.builder();
dataOut.flush();
dataOut.close();
while (true)
{
intStreamBuilder.accept(
inputStream.readInt());
}
}
catch (IOException exception)
{
throw new RuntimeException(exception);
}
catch (EOFException ignoredException)
{
// logic to be executed after stream has been fully read
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
}
finally
{
if (inputSream != null)
{
try
{
inputStream.close();
}
catch (IOException exception)
{
throw new RuntimeException(exception);
}
}
}
}
The try inside the finally is required.
I prefer the try-with-resources construct.
If I were you I will change my code to be as the following
//try-with-resources-close
try (DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(
this.byteOut.toByteArray())))) {
IntStream.Builder intStreamBuilder = IntStream.builder();
byte[] byts = new byte[4];
while (inputStream.read(byts) > -1) {// read 4 bytes and convert them to int
int result = ByteBuffer.wrap(byts).getInt();
intStreamBuilder.accept(result);
}
// logic to be executed after stream has been fully read
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
} catch (IOException e) {
throw new RuntimeException(e);
}
try-with-resources this new way added in Java 7 to close any object that implements AutoCloseable automatically when try block is executed
readInt method it works as the following read 4 bteys then convert them to int
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
//So you also can do the same thing, but instead of throws EOFException
you can add return false or break the loop
for read bytes method if no bytes existed then it reture -1
Well the better solution I found thanks to #Oliver Charlesworth is the following:
try (DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(this.byteOut.toByteArray())))) {
while (true)
intStreamBuilder.accept(inputStream.readInt());
} catch (EOFException e) {
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
} catch (IOException e) {
throw new RuntimeException(e);
}
This still has logic inside the catch block the code look definitely cleaner.
However, I cannot come up with a better approach that determines that the InputDataStream has been fully read.
What bugs me about this is that reaching the end of the stream is expected and it would actually be exceptional if no exception was thrown, what IMO defeats the purpose of exceptions in the first place.
I asked a separate question of the possible use of Java NIO's IntBuffer class here. My above snippet could be changed to:
IntBuffer intBuffer = ByteBuffer.wrap(this.byteOut.toByteArray()).asIntBuffer();
while (intBuffer.hasRemaining()){
intStreamBuilder.accept(intBuffer.get());
}
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
I have trouble with the Java Sockets.
I need to connect a server and a client through the local network and as there can be more then two devices connected to the router the Client must find out the Address of the server.
The only way I know to solve this problem is to get the three first numbers of the clients IP(v4)-address and loop every of the 254 other possible IPs.
(I know that this way is very slow and may cause many problems. If you know an alternative, I will be glad).
Actually the client is an android smartphone so I can get the DHCP-Info.
The problem is, that the read command to check if a device is a server will last forever.
If you need some code, here it is!
code:
onCreate:
final WifiManager manager = (WifiManager) super.getSystemService(WIFI_SERVICE);
final DhcpInfo dhcp = manager.getDhcpInfo();
final String address = intToIp(dhcp.ipAddress);
String addresspart=address.substring(0, address.lastIndexOf('.')+1);
ArrayList<HashMap<String, String>> l = null;
Log.d("Keyboard","initiating search");
try {
l = new checkConnections().execute(addresspart).get();
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
}
checkConnections:
ArrayList<HashMap<String,String>> l=new ArrayList<HashMap<String,String>>();
for(int i=1;i<=255;i++){
try {
worksocket=new Socket(addresspart[0]+i,61927);
workout=new BufferedOutputStream(worksocket.getOutputStream());
workin=new BufferedInputStream(worksocket.getInputStream());
byte[] buffer=new byte[6];
workin.read(buffer);//at this point the app freezes until you stop the serverside program
String answer=new String(buffer,"UTF-8");
Log.i("Keyboard","Welcome Message: "+answer);
if(answer.equalsIgnoreCase("sdk on")){
HashMap<String,String> hm=new HashMap<String,String>();
hm.put("address",addresspart[0]+i);
l.add(hm);
workout.write(intToBytes(8));
workout.write("closing".getBytes("UTF-8"));
worksocket.close();
continue;
}
else{
Log.d("Keyboard","No SDK-Programm detected");
worksocket.close();
continue;
}
} catch (UnknownHostException e) {
Log.d("Keyboard",addresspart[0]+i+" doesn't exists");
continue;
} catch ( InterruptedIOException e){
Log.w("System.warn",e.getCause()+e.getLocalizedMessage());
Log.d("Keyboard","timeout");
continue;
} catch (IOException e) {
Log.d("Keyboard",addresspart[0]+i+" doesn't exists");
e.printStackTrace();
continue;
}
}
return l;
the server's code:
ServerSocket serverSocket = new ServerSocket(61927);
System.out.println("Socket initiated");
Socket client = serverSocket.accept();
BufferedInputStream in=new BufferedInputStream(client.getInputStream());
BufferedOutputStream out=new BufferedOutputStream(client.getOutputStream());
System.out.println("client found");
byte[] buffer=new byte[11];
out.write("sdk on".getBytes("UTF-8"));
in.read(buffer);
String s=new String(buffer,"UTF-8");
if(!s.equals("got info")){
System.out.println("No SDK Client");
client.close();
serverSocket.close();
new Main();
}
Uh, I think I should ping the Broadcast-IP and listen for answers instead...
Android's Linux runtime allows it to read from which IP an answer is coming.
Here's my situation: I'm using IOUtils to copy a file. The next thing I do is send a JSON message to another program to say, "You can download the copy". The problem is about 25% of the time the other program gets an error saying "Received unexpected EOF downloading artifact".
Every time this error occurs, if I try again manually, the error doesn't occur. My theory is that IOUtils.copy doesn't block and the OS is still writing the file to the FS while the other program tries to download it. Is there a way to force IOUtils.copy or other functionally equivalent code to block until the OS has finished writing the file? Or is my theory incorrect? Here's the code I'm using:
private boolean archiveArtifact(String archivePath, String deployId, Artifact artifact) {
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
boolean successful = true;
try {
File archiveDir = new File(archivePath);
File deployDir = new File(archiveDir, deployId);
if (!deployDir.exists()) {
deployDir.mkdirs();
}
URLConnection connection = new URL(artifact.getJenkinsUrl()).openConnection();
inputStream = connection.getInputStream();
File output = new File(deployDir, artifact.getFileName());
fileOutputStream = new FileOutputStream(output);
IOUtils.copy(inputStream, fileOutputStream);
} catch (IOException e) {
successful = false;
logger.error(e.getMessage(), e);
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
successful = false;
logger.error(e.getMessage(), e);
}
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
successful = false;
logger.error(e.getMessage(), e);
}
}
return successful;
}
It might be worth noting that I'm copying this to a NFS. Keep in mind I don't really know anything about NFS. This is CentOS release 5.9 (Final).
Your current code only ensures that the file content is passed to the operating system for writing; it does not guarantee that it is actually written to a the disk.
To be certain that the file is actually written to disk you can call sync() on the FileDescriptor:
fileOutputStream.flush();
fileOutputStream.getFD().sync();
I've seen many different examples of using HttpURLConnection + InputStream, and closing them (or not closing them) after use. This is what I came up with to make sure everything is closed after finished, whether there's an error or not. Is this valid?:
HttpURLConnection conn = null;
InputStream is = null;
try {
URL url = new URL("http://example.com");
// (set connection and read timeouts on the connection)
conn = (HttpURLConnection)url.openConnection();
is = new BufferedInputStream(conn.getInputStream());
doSomethingWithInputStream(is);
} catch (Exception ex) {
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (conn != null) {
conn.disconnect();
}
}
Thanks
Yep.. Doing the end part in finally would be best idea because if code fails somewhere, program won't reach till .close(), .disconnect() statements that we keep before catch statements...
If the code fails somewhere and exception is thrown in between of the program, still finally get executed regardless of exception thrown...
There is also the new (with Java 7) 'try()' technique
try (OutputStream os = http.getOutputStream()) {
os.write(out);
}
Basically, it will auto-close anything in the try() statement, regardless of whether it is successful or not.
I am trying to use the RXTX library for blocking serial communication on Windows (XP and 7). I have tested the connection with Hyperterminal in both ends, and it works flawlessly.
I set up the connection with the following code: (exception handling and defensive checks omitted for clarity)
private InputStream inStream;
private OutputStream outStream;
private BufferedReader inReader;
private PrintWriter outWriter;
private SerialPort serialPort;
private final String serialPortName;
public StreamComSerial(String serialPortName) {
this.serialPortName = serialPortName;
CommPortIdentifier portIdentifier;
portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);
CommPort commPort = null;
commPort = portIdentifier.open(this.getClass().getName(),500);
serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(4800,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
inStream = serialPort.getInputStream();
outStream = serialPort.getOutputStream();
inReader = new BufferedReader(new InputStreamReader(inStream, Settings.getCharset()));
outWriter = new PrintWriter(new OutputStreamWriter(outStream, Settings.getCharset()));
When I use
outWriter.println("test message");
flush();
the message is recieved fine on the other end, but calling
inReader.readLine()
imidiately returns "java.io.IOException: Underlying input stream returned zero bytes".
I then decided to try and implement my own blocking read logic and wrote this:
public String readLine() throws IOException {
String line = new String();
byte[] nextByte = {-1};
while (true) {
nextByte[0] = (byte)inStream.read();
logger.debug("int read: " + nextByte[0]);
if (nextByte[0] == (byte)-1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
logger.debug("byte read: " + nextByte[0]);
line = line + new String(nextByte);
if (nextByte[0] == (byte)13) { // 13 is carriage return in ASCII
return line;
}
}
}
But this code goes in an infinite loop and "nextByte[0] = (byte)inStream.read();" assigns -1 no matter what is sent over the serial connection. In addition, the other end stutters quite badly and only lets me send a character every 1-3 sec. and hangs for a long time if I try to send many characters in a short burst.
Any help very appreciated.
*edit - using inStream.read(nextByte) instead of "nextByte[0] = (byte)inStream.read();" does not write to the nextByte variable, no matter what I send to it through the serial connection.
*edit2 - as my code works flawlessly with the SUN javax.comm lib and a win32com.dll I got from a friend, I have ceased trying to make it work with RXTX. I am not interested in unblocking communication, which seems to be the only way other people can make RXTX work.
Use RXTX-2.2pre2, previous versions have had a bug which prevented blocking I/O from working correctly.
And do not forget to set port to blocking mode:
serialPort.disableReceiveTimeout();
serialPort.enableReceiveThreshold(1);
I think the code you wrote in your own readLine implementation is buggy. nextByte[0] is never restored to -1 after the first character is read.
You should try to use the value returned by inStream.read(nextByte) to state the number of bytes read from the stream instead of the value of your byte array.
Anyway I think you should go for an event based method of reading the inputs with a SerialPortEventListener:
serialPort.addEventListener(new SerialPortEventListener() {
public void serialEvent(SerialPortEvent evt) {
switch (evt.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
dataReceived();
break;
default:
break;
}
}
});
serialPort.notifyOnDataAvailable(true);
it may not be blocking but when the stream is empty, just catch the IOE and keep reading from it. This is what I do with RXTX-2.1-7 and it works fine, I use it to read and write to an arduino:
public static class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
Boolean keepRunning = true;
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while (keepRunning) {
try {
while ((line = br.readLine()) != null) {
//DO YOUR STUFF HERE
}
} catch (IOException e) {
try {
//ignore it, the stream is temporarily empty,RXTX's just whining
Thread.sleep(200);
} catch (InterruptedException ex) {
// something interrupted our sleep, exit ...
keepRunning = false;
}
}
}
}
}
I have solved this way
try
{
if(input.ready()==true)
{
String inputLine=input.readLine();
System.out.println(inputLine);
}
} catch (Exception e)