F
Fritz Bayer
Hello,
I'm having problems with writting data to a SocketChannel. The problem
is that my program gets caught in an infinite loop, after running for
hours without a problem.
I have a ByteBuffer containing data, which I want to write to a
SocketChannel. I do this the whole time again and agian, until the
ByteBuffer is empty and then I continue.
This happens over and over again.
The problem is though that once in a while (usually after a couple of
hours) no data can be written to the SocketChannel and therefore I end
up in an infinite loop.
On the other hand I can't just continue, when no bytes have been
written, since that actually happens almost all of the time, when
writting data to the channel. It almost always takes a couple of
writes to empty the whole ByteBuffer. And inbetween those writes you
get zero writes, which means no bytes had been written, as well.
Here is the important code snippet:
int bytesRead = 0;
byteBuffer.clear();
int loops = 0;
while ((bytesRead = inputChannel.read(byteBuffer)) > 0)
{
timestampOfLastRead = System.currentTimeMillis();
byteBuffer.flip();
long lastTimeWeReadBytes = System.currentTimeMillis();
while (byteBuffer.hasRemaining())
{
int bytesWritten = outputChannel.write(byteBuffer);
if (bytesWritten != 0)
lastTimeWeReadBytes = System.currentTimeMillis();
else
assert System.currentTimeMillis() - lastTimeWeReadBytes < 60000 :
" We are trying since " + (System.currentTimeMillis() -
lastTimeWeReadBytes) + " ms to write data to a socket channel and have
failed. This is bad. How do we avoid this. We can't just stop if
byteesWritten=0 since thats very often the case";
}
assert byteBuffer.limit() > 0 && byteBuffer.capacity() > 0 && !
byteBuffer.hasRemaining() : "Of course this has to be true after we
are done. If not somthing is really messed up";
}
This writting stuff is confusing. I know that usually you get informed
when data can be written to a socketchannel.
However, this funtion get basically called on every key on every
selection, since most of the time data can be written.
And actually I read on the sun site that you just write the data when
you have it to the socketchannel.
However, I know from pratice that:
1. To empty a ByteBuffer and to write all its data you have to call
write several times. Sometimes you write small chunks. Sometimes you
write nothing. And sometimes you write all the data at once.
2. If you follow the policy that you stop writting, when no data was
written you are left with data which still has to be send.
If you don't get another isReadable() call on the input SocketChannel,
then you won't be able to send the data at all and the other side
never gets it, which is bad too.
3. If you write until the ByteBuffer has been emptied, then this works
for hours. But it fails after a while. What happens is that you will
write no bytes at all forever.
I thought about to check the SelectorKey.isWriteable before writting
the data and stop writting data if the call return false.
However, then I'm stuck with unsent data. Of course that's better then
being stuck in an infinte loop.
However, I would be very happy about some feedback from the
experienced and practice proven nio programmers. If you know about
this problem I would be very happy to hear what you suggest!
Fritz
I'm having problems with writting data to a SocketChannel. The problem
is that my program gets caught in an infinite loop, after running for
hours without a problem.
I have a ByteBuffer containing data, which I want to write to a
SocketChannel. I do this the whole time again and agian, until the
ByteBuffer is empty and then I continue.
This happens over and over again.
The problem is though that once in a while (usually after a couple of
hours) no data can be written to the SocketChannel and therefore I end
up in an infinite loop.
On the other hand I can't just continue, when no bytes have been
written, since that actually happens almost all of the time, when
writting data to the channel. It almost always takes a couple of
writes to empty the whole ByteBuffer. And inbetween those writes you
get zero writes, which means no bytes had been written, as well.
Here is the important code snippet:
int bytesRead = 0;
byteBuffer.clear();
int loops = 0;
while ((bytesRead = inputChannel.read(byteBuffer)) > 0)
{
timestampOfLastRead = System.currentTimeMillis();
byteBuffer.flip();
long lastTimeWeReadBytes = System.currentTimeMillis();
while (byteBuffer.hasRemaining())
{
int bytesWritten = outputChannel.write(byteBuffer);
if (bytesWritten != 0)
lastTimeWeReadBytes = System.currentTimeMillis();
else
assert System.currentTimeMillis() - lastTimeWeReadBytes < 60000 :
" We are trying since " + (System.currentTimeMillis() -
lastTimeWeReadBytes) + " ms to write data to a socket channel and have
failed. This is bad. How do we avoid this. We can't just stop if
byteesWritten=0 since thats very often the case";
}
assert byteBuffer.limit() > 0 && byteBuffer.capacity() > 0 && !
byteBuffer.hasRemaining() : "Of course this has to be true after we
are done. If not somthing is really messed up";
}
This writting stuff is confusing. I know that usually you get informed
when data can be written to a socketchannel.
However, this funtion get basically called on every key on every
selection, since most of the time data can be written.
And actually I read on the sun site that you just write the data when
you have it to the socketchannel.
However, I know from pratice that:
1. To empty a ByteBuffer and to write all its data you have to call
write several times. Sometimes you write small chunks. Sometimes you
write nothing. And sometimes you write all the data at once.
2. If you follow the policy that you stop writting, when no data was
written you are left with data which still has to be send.
If you don't get another isReadable() call on the input SocketChannel,
then you won't be able to send the data at all and the other side
never gets it, which is bad too.
3. If you write until the ByteBuffer has been emptied, then this works
for hours. But it fails after a while. What happens is that you will
write no bytes at all forever.
I thought about to check the SelectorKey.isWriteable before writting
the data and stop writting data if the call return false.
However, then I'm stuck with unsent data. Of course that's better then
being stuck in an infinte loop.
However, I would be very happy about some feedback from the
experienced and practice proven nio programmers. If you know about
this problem I would be very happy to hear what you suggest!
Fritz