Name: nt126004 Date: 02/22/2002
FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :Linux RedHat 7.2
A DESCRIPTION OF THE PROBLEM :
I try to use following codes to delivery a file from a
Linux machine. When the size of file is larger than 64K
bytes,the program is stuck. Howerver,the same program is
working fine at a windows 2000 Advanced Server machine.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
No error message.
STEPS TO REPRODUCE:
1.Install Red Hat 7.2 on a computer .
2.Download Java 1.4 RPM package and install it.
3.Prepare a large file(test.txt) and put the file into the same directory as
SampleServer.
3.Run SampleServer.
4.Run telnet to port 9988 at same machine.
You should be getting the content of whole test.txt file. However,you will
only get part of the file.The server will hang at some place in the file
while sending the data. Each time you hit "Enter" another request for
getting the file will be sent to the server.All requests after the first
will complete without problem.
If you telnet from Windows or Solaris machine, all requests will hang at same
place in the middle of file.
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.nio.charset.*;
import java.net.*;
import java.util.*;
/**
* Using Java Merlin's new i/o package to deliver a nonblocking server.
*/
public class SampleServer implements Runnable {
private static final int PORT=9988;
private int port = PORT;
private Selector selector = null;
private ServerSocketChannel selectableChannel = null;
private int keysAdded = 0;
private boolean connectionIsMade=false;
private InetAddress lh;
private Thread thread;
/**
* Create a rais server by using default parameters.
* web directory=c:\\temp
*/
public SampleServer() {
}
/**
* Initializes selector and specifies the channel to nonblocking =
states.
*/
public void initialize() throws IOException {
this.selector = SelectorProvider.provider().openSelector();
this.selectableChannel = ServerSocketChannel.open();
this.selectableChannel.configureBlocking(false);
lh = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(this.port );
this.selectableChannel.socket().bind(isa);
}
/**
* close channel and selector before the object is been destoried.
*/
public void finalize() throws IOException {
this.selectableChannel.close();
this.selector.close();
}
/**
* Begins to accept connections which are come from clients.
*/
public void acceptConnections()throws IOException, InterruptedException {
selectableChannel.register(selector,SelectionKey.OP_ACCEPT);
SelectionKey acceptKey = selectableChannel.register(selector,
SelectionKey.OP_ACCEPT);
System.out.println( "Waiting for connection......" );
connectionIsMade=false;
while (( this.keysAdded = acceptKey.selector().select()) > 0 ) {
Set readyKeys = this.selector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
SelectionKey key = (SelectionKey)i.next();
i.remove();
if ( key.isAcceptable() ) {
System.out.println("accepting a connection");
ServerSocketChannel nextReady = (ServerSocketChannel)key.channel();
SocketChannel channel = nextReady.accept();
channel.configureBlocking( false );
SelectionKey readKey = channel.register( this.selector,
SelectionKey.OP_READ|SelectionKey.OP_WRITE);
readKey.attach( new ChannelCallback( channel ) );
}
else if ( key.isReadable() ) {
System.out.println("reading a message");
this.readMessage( (ChannelCallback) key.attachment() );
}
else if ( key.isWritable() && !connectionIsMade) {
connectionIsMade=true;
ChannelCallback callback = (ChannelCallback) key.attachment();
}
}
}
System.out.println( "End acceptor loop..." );
}
public static void main (String args[])
{ SampleServer S=new SampleServer();
S.start();
}
/**
* Sends a file to client.
* @param channel current channel.
* @param filename file to be sent.
*/
public void writeFile(SocketChannel channel,String filename) throws
IOException{
System.out.println("writeFile()");
ByteBuffer[] bf=new ByteBuffer[2];
String message="226 transfer completed.\r\n";
bf[1]= ByteBuffer.wrap( message.getBytes() );
try{
FileInputStream fis = new FileInputStream(new File(filename));
FileChannel fc = fis.getChannel();
// Get the file's size and then map it into memory
int sz = (int)fc.size();
bf[0]=fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
channel.write( bf );//Due to the nonblocking,I have to send = data and message togather
fc.close();
}catch(FileNotFoundException e){
}
}
private String decode( ByteBuffer byteBuffer )
throws CharacterCodingException {
Charset charset = Charset.forName( "us-ascii" );
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode( byteBuffer );
String result = charBuffer.toString();
return result;
}
/**
* Reads an message from client.
* @param callback callback object.
*/
static final int BUFSIZE = 8;
public void readMessage( ChannelCallback callback )
throws IOException, InterruptedException {
ByteBuffer byteBuffer = ByteBuffer.allocate( BUFSIZE );
int nbytes = callback.getChannel().read( byteBuffer );
byteBuffer.flip();
String result = this.decode( byteBuffer );
// System.out.println( result );
callback.append( result.toString() );
if ( result.indexOf( "\n" ) >= 0 )
callback.execute();
}
/**
* Start this class as a thread.
*/
public void start() {
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setName("RaisServer");
thread.start();
}
/**
* Stops the current thread.
*/
public synchronized void stop() {
thread=null;
notify();
try{finalize();}catch(IOException e){}
System.out.println("Server is down.");
}
/**
* Run method.
*/
public void run(){
Thread me=Thread.currentThread();
try {
initialize();
} catch ( IOException ioe ) {
ioe.printStackTrace();
System.exit( -1 );
}
while (thread == me ) {
try {
acceptConnections();
}
catch ( IOException e ) {
e.printStackTrace();
System.out.println( e );
}
catch ( InterruptedException e ) {
System.out.println( "Exiting normally..." );
break;
}
}
}
/**
* Inner class to define a class back object for manipulate multil =
users.
*/
class ChannelCallback {
private SocketChannel channel;
private StringBuffer buffer;
/**
* Constructor.
* @param channel current returned channel.
*/
public ChannelCallback( SocketChannel channel ) {
this.channel = channel;
this.buffer = new StringBuffer();
}
/**
* Executes the commands which are come from clients.
*/
public void execute() throws IOException, InterruptedException {
System.out.println("execute");
String commandstr=buffer.toString();
writeFile(channel,"test.txt");
buffer = new StringBuffer();
}
/**
* Returns current channel.
*/
public SocketChannel getChannel() {
return this.channel;
}
/**
* Appends reading string to buffer for future processing.
*/
public void append( String values ) {
buffer.append( values );
}
}
}
---------- END SOURCE ----------
(Review ID: 138205)
======================================================================