I have a problem with my Java socket and connection. It seems like my input stream does not read any data even though there is data on the stream. Here is an example on how we read data:
InputStream is = socket.getInputStream();
StringBuffer buf = new StringBuffer();
final int SO_TIME = 2500;
socket.setSoTimeout(SO_TIME);
long readTime = 0;
boolean remoteSocketClosed = false;
//Read data while the Remote-Socket is opened and the timeout is OK
while (!remoteSocketClosed && readTime < 30000)
{
try
{
int c = is.read();
if (c != -1)
{
buf.append((char)c);
}
else //c==-1
{
remoteSocketClosed = true;
}
}
catch (SocketTimeoutException socketTimeout)
{
readTime += SO_TIME;
}
}
if (readTime >= 30000)
{
throw new IOException("No answer from server after request (" + readTime +"ms )");
}
else
{
if (buf.length() > 0)
{
return buf;
}
else
{
return null;
}
}
finally
{
try
{
if (socket!=null)
socket.close();
}
catch (Exception e)
{
l.error("Socket not closed", e);
}
try{Thread.sleep(250);}catch(Exception e){}
}
Now this looks fine to me. However when there is data on the stream, it will not get picked up. I can use telnet and see that data is coming in on that connection, yet Java just throws the IOException (timeout).
The server is running on the same machine (localhost), and we can send data to the server, yet the answer is lost somehow (only in Java not in telnet). Is this some weird setting I don't know about? We are using Windows 10 and Java 8, firewalls are all disabled. I have never experienced something like this so any help is appreciated.
Sometimes you just don't see the forest for the trees and have to sleep over it...
The problem is my condition
if (c != -1)
{
buf.append((char)c);
}
else //c==-1
{
remoteSocketClosed = true;
}
But the server never closes the connection... So I never exit my loop and im stuck for 30 seconds running into socket timeouts. After the 30 seconds of waiting my answer is in the StringBuffer but of course my readTime is 30000 so I throw the exception rather providing an answer... I will have to think of an EndOfPackage Byte or something to avoid this.
Thanks for any help tho
Related
I've a class which is responsible for listening two other machines which have exactly the same classes, so it's a network of three computers having the same code. The connection is there and I can see them passing data to each other. Everything until there works OK.
Things get tricky when I take out one of the machines and observe how the other two behave. Expectedly, when one of the machines stops working for some reason, other two should continue. And if two of them stop, the remaining should go on.
I tried to implement this mechanism below. However, when I take out one of the machines, the program keeps waiting, so it does not switch to "two-way comparison mode".
public void listen() {
try {
logger.info("Creating listener sockets");
while (isRunning) {
final byte[] buf = new byte[bufferSize];
final DatagramPacket packetOne = new DatagramPacket(buf, buf.length);
final DatagramPacket packetTwo = new DatagramPacket(buf, buf.length);
MediatorMessageMsg mediatorMessageOne = null;
MediatorMessageMsg mediatorMessageTwo = null;
try {
socketReceiverOne.receive(packetOne);
ByteArrayInputStream firstInput = new ByteArrayInputStream(buf);
mediatorMessageOne = MediatorMessageMsg.parseDelimitedFrom(firstInput);
socketReceiverTwo.receive(packetTwo);
ByteArrayInputStream secondInput = new ByteArrayInputStream(buf);
mediatorMessageTwo = MediatorMessageMsg.parseDelimitedFrom(secondInput);
logger.trace("Received packets");
} catch (final SocketTimeoutException e) {
logger.trace(e.getMessage());
continue;
} catch (final SocketException e) {
logger.warn(e);
logger.warn("Ignore the error and go on.");
continue;
} catch (final IOException e) {
logger.error("Incoming communication stopped!");
logger.error(e);
stop();
}
// if two mediators sent the data, it's OK
if (packetOne.getLength() > 0 && packetTwo.getLength() > 0) {
handlePackets(mediatorMessageOne, mediatorMessageTwo);
logger.info("Number of active mediators: 2. Comparison style: 1v1v1");
}
// if only one sent the data, compare it with our own
else if (packetOne.getLength() > 0 || packetTwo.getLength() > 0) {
// whicehever sent the data, compare its data with our own
logger.info("Number of active mediators: 1. Comparison style: 1v1");
if (packetOne.getLength() > 0) {
handlePackets(mediatorMessageOne);
} else {
handlePackets(mediatorMessageTwo);
}
}
// if no data is sent, then pass our own directly
else {
logger.info("Number of active mediators: 0. Comparison style: No Comparison");
// our datamodel to retrieve data on our own
DataModel modelOwn = DataModel.getInstance();
MediatorMessageMsg newMessage = MediatorMessageMsg.newBuilder().setHeading(modelOwn.getHeading()).setSpeed(modelOwn.getSpeed()).setSender(getId()).build();
// publish(topicName, newMessage);
}
Thread.sleep(1);
}
socketReceiverOne.close();
socketReceiverTwo.close();
logger.info("stopped");
} catch (final IllegalArgumentException e) {
logger.error("Illegal argument received: " + e);
} catch (final Exception e) {
logger.error("Unexpected error occured: " + e);
} finally {
if (socketReceiverOne instanceof DatagramSocket && socketReceiverTwo instanceof DatagramSocket) {
if (!socketReceiverOne.isClosed() || !socketReceiverTwo.isClosed()) {
socketReceiverOne.close();
socketReceiverTwo.close();
}
}
}
}
To save your time, let me share my opinion on the matter. I suspect the problem to be in this part:
socketReceiverOne.receive(packetOne);
ByteArrayInputStream firstInput = new ByteArrayInputStream(buf);
mediatorMessageOne = MediatorMessageMsg.parseDelimitedFrom(firstInput);
socketReceiverTwo.receive(packetTwo);
ByteArrayInputStream secondInput = new ByteArrayInputStream(buf);
mediatorMessageTwo = MediatorMessageMsg.parseDelimitedFrom(secondInput);
To me it seems like the program expects a package and when it cannot receive it, it keeps waiting. Although I have time out exception condition, I cannot get this done.
private int socketTimeout = 1000 * 2;// 2sec
socketReceiverOne.setSoTimeout(socketTimeout);
socketReceiverTwo.setSoTimeout(socketTimeout);
Any thoughts?
Okay I found where I was mistaken. I needed more ports (for in and out). Once I incorporated those ports, the problem did not occur again.
public static void waitUntil(String prompt, InputStream instr) {
while (true) {
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (instr.available() >= 5) {
byte[] buff = new byte[1024];
int ret_read = 0;
ret_read = instr.read(buff);
if (ret_read > 0) {
if ((new String(buff, 0, ret_read)).contains(prompt)
&& flag) {
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
If if remove that thread.sleep(1000) or even i reduce the to less than 1000 its not working properly.
Question : How to read java socket inputstream without thread.sleep() till all all incoming bytes are arrived?
if (instr.available() >= 5) {
Don't do that.
Instead of checking how many bytes are available, just try to read some into a buffer.
That will block until at least one byte is available, and then return as many as there are (that also fit into the buffer).
If that does not return all the bytes you need, loop until you get them.
If you just want to read everything, check out this thread: Convert InputStream to byte array in Java . Personally, I use Commons IO for this.
Use DataInputStream.readFully() with a buffer size of 5 (in this case, or more generally the size of data you're expecting), and get rid of both the sleep and the available() test.
I am working on a program for Android, which connects to a server via SSH to get some data.
The problem is, in the event a command is sent to the server, that doesn't return anything (such as cat on an empty file), my program hangs, seemingly being blocked by in.read().
I have a breakpoint on the the line
if ((read = in.read(buffer)) != -1){
and on the then/else lines below it. If I debug it, the program breaks normally on the if-statement, but when I hit continue, the program just hangs again, and never makes it to the next breakpoint.
The program works normally if it actually gets a response from the server, but I'd like to protect my program from a hang if the server isn't cooperating properly.
I am using the J2SSH library.
public String command(String command) {
command = command + "\n";
if (session.getSessionType().equals("Uninitialized") || session.isClosed()) {
openShell();
}
OutputStream out = session.getOutputStream();
InputStream in = session.getInputStream();
byte buffer[] = new byte[255];
int read;
String in1 = null;
String fullOutput = "";
try {
try {
out.write(command.getBytes());
} catch (IOException e){
Log.e(TAG,"Error writing IO stream");
e.printStackTrace();
}
boolean retrivingdata = true;
while (retrivingdata){
String iStreamAvail = "Input Stream Available "+ in.available();
if ((read = in.read(buffer)) != -1){
retrivingdata = true;
} else {
retrivingdata = false;
return null;
}
in1 = new String(buffer, 0, read);
fullOutput = fullOutput + in1;
if (read < 255){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return fullOutput;
}
Reading and writing should be done in separate threads. read() is a blocking method that waits until data is available from the server.
i have a java client-server app in java, both using the same connection class that contains both send/receive messages.
for some reason, some of the messages i send are received in a malformed order:
here's the code
//set up
_in = new BufferedReader(new InputStreamReader(this._socket.getInputStream()));
_out = new BufferedWriter(new OutputStreamWriter(this._socket.getOutputStream()));
this._socket.setSoTimeout(S_TIMEOUT);
public synchronized boolean send(String message){
try {
_out.write(message);
_out.write(Connection.DELIMITER);
_out.flush();
return true;
} catch (IOException e) {
}
return false;
}
public String receive(){
int c;
try {
String message = "";
System.out.println("Getting message:");
c = _in.read();
while(c != -1 && c != Connection.DELIMITER) {
message += (char) c;
c = _in.read();
}
if (c == -1) {
return null;
}
return message;
} catch (IOException e) { }
return null;
}
some messages, for example "new_order" will might return with "ew_ord".
some characters are lost, others are sent separately. this seems odd as its TCP
could this be an encoding related issue?
Delimiter is (char) 0
socket timeout is 20000 (ie 20 senconds). every 10 seconds i send an empty message to make sure socket does not close
EDIT:
although it was solved using the Scanner, i must say that the original code worked fine for many messages/various machines for a very long time (a few weeks), and then suddenly failed to work with one specific message on one specific machine (other messages went through just fine). i've done socket data transfer in java MANY times and i've written many read/write methods to handle the sockets. it's the first time i ran into this.
although in the original code i set the encoding (in the posted code i didn't), i believe that the problem was encoding related. at one point, the message that was received had every second character missing. afterwards i changed it a bit, and the first/second character of the message were received in a separate message. from my understanding, it's either an encoding issue or some firewall/other security program that was running on the message sender machine, that decided to filter outgoing packets.
Try replacing your receive with a Scanner and let it do the work for you.
// in your setup
Scanner sc = new Scanner(_in).useDelimiter(Connection.DELIMETER);
public String receive() {
try {
return sc.next();
} catch(IOException e) {
return "";
}
}
For starters, I would make sure you're printing exceptions in those catch blocks.
Then, you're using the platform default encoding for converting characters to bytes. If these two processes are running on different machines, it's possible they're using different encodings. I would make sure you're specifying an encoding when you set up the Reader and Writer.
You can use UTF encoding for getting Full String of Message.
U can try this code and I am Sure About this code because i used it in My Chat Application.
String data=" ";
socket = new Socket("localhost",999);
while(true)
{
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
data = dis.readUTF();
jta.append(data +"\n");
}
Where jta is JTextArea.
It's for Client Side
Now For Server Side:
try
{
server = new ServerSocket(999);
Socket soc = server.accept();
while(true)
{
String data="";
try
{
dis = new DataInputStream(soc.getInputStream());
dos = new DataOutputStream(soc.getOutputStream());
data = dis.readUTF();
}
catch(Exception e)
{ }
jta.append(data + "\n");
}
}
catch (IOException e)
{
JOptionPane.showMessageDialog(this, e);
System.exit(-1);
}
How can i solve this problem. I got following error:
java.nio.channels.ClosedChannelException
This is coding:
public void run() {
try {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(512);
int i1 = socketChannel.read(buffer);
if (buffer.limit() == 0 || i1 == -1) {
Socket s = null;
try {
s = socketChannel.socket();
s.close();
key.cancel();
} catch (IOException ie) {
if (UnitDataServer.isLog) {
log.error("Error closing socket " + s + ": " + ie);
}
}
} else {
buffer.flip();
if (UnitDataServer.isLog) {
log.info(" Recvd Message from Unit : " + buffer.array());
}
byte byteArray[] = buffer.array();
log.info("Byte Array length :" + byteArray.length);
hexString = new StringBuffer();
for (int i = 0; i < i1 /* byteArray.length */; i++) {
String hex = Integer.toHexString(0xFF & byteArray[i]);
if (hex.length() == 1) {
// could use a for loop, but we're only dealing with a
// single byte
hexString.append('0');
}
hexString.append(hex);
}
hexString.trimToSize();
log.info("Hex String :" + hexString);
Communicator.dataReceive(new DataReceive(
socketChannel, hexString.toString(), dst));
}
} catch (Exception e) {
if (UnitDataServer.isLog) {
// log.error(e);
}
try {
socketChannel.socket().close();
key.cancel();
} catch (IOException ex) {
if (UnitDataServer.isLog) {
log.error(ex);
}
}
}
}
You have closed the channel and are still trying to use it.
There are several issues with your code.
First, your test for EOS is faulty. Remove the limit() == 0 test. That doesn't indicate EOS, it just indicates a zero length read, which can happen in non-blocking mode at any time. It doesn't mean the peer has closed his end of the connection, and it doesn't mean you should close your end.
Second, closing a channel closes the socket as well. You should close the channel only, not the socket.
Third, closing a channel cancels the key. You don't need to follow every close with a cancel.
You may also have failed to check whether a ready key is valid in the select loop before using it, e.g. for reading.
I continue to be amazed, and amused, and bemused, by the claim elsewhere in this thread that 'source code is untrue' under some circumstances.
You need to fix/secure code that is throwing this exception. ClosedChannelException is ...
... thrown when an
attempt is made to invoke or complete
an I/O operation upon channel that is
closed, or at least closed to that
operation. That this exception is
thrown does not necessarily imply that
the channel is completely closed. A
socket channel whose write half has
been shut down, for example, may still
be open for reading
(as described in Java 6 API)
But really, you would need to provide us code snipped and stack trace in order to get more detailed help.