⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bytebufferoutputstream.java

📁 一个用java编写的服务器,对于学习网络编程的人来说是个很好的例子
💻 JAVA
字号:
/*
 * This file is part of the QuickServer library 
 * Copyright (C) QuickServer.org
 *
 * Use, modification, copying and distribution of this software is subject to
 * the terms and conditions of the GNU Lesser General Public License. 
 * You should have received a copy of the GNU LGP License along with this 
 * library; if not, you can download a copy from <http://www.quickserver.org/>.
 *
 * For questions, suggestions, bug-reports, enhancement-requests etc.
 * visit http://www.quickserver.org
 *
 */

package org.quickserver.util.io;

import java.io.*;
import java.nio.*;
import java.util.*;
import org.apache.commons.pool.ObjectPool;
import org.quickserver.net.server.ClientHandler;
import org.quickserver.net.server.impl.NonBlockingClientHandler;
import java.util.logging.*;

/**
 * This is an OutputStream constructed from list of ByteBuffers. This is
 * used in non-blocking mode.
 * @since 1.4.5
 * @author Akshathkumar Shetty
 */
public class ByteBufferOutputStream extends OutputStream {
	private static Logger logger = Logger.getLogger(ByteBufferOutputStream.class.getName());
	static {
		logger.setLevel(Level.INFO);
	}

	/**
	 * Sets the debug flag. When debug is set to <code>true</code>
	 * one can see number of bytes written.
	 */
	public static void setDebug(boolean flag) {
		if(flag) 
			logger.setLevel(Level.FINEST);
		else
			logger.setLevel(Level.INFO);
	}
	
	/**
	 * @since 1.4.7
	 */
	public static boolean isLoggable(Level level) {
		return logger.isLoggable(level);
	}

	private ArrayList bufferList;
	private ByteBuffer lastByteBuffer = null;
	private NonBlockingClientHandler handler;
	private Object toNotify = null;

	/**
	 * Creates a new ByteBufferOutputStream using the given list as its base
	 * and ClientHandler as the target channel.
	 */
	public ByteBufferOutputStream(ArrayList bufferList, ClientHandler handler) {
		if(bufferList==null || handler==null)
			throw new IllegalArgumentException("ArrayList or ClientHandler was null.");
		this.bufferList = bufferList;
		this.handler = (NonBlockingClientHandler) handler;
	}

	public synchronized void close() {
		if(lastByteBuffer!=null) {
			returnBufferBack(lastByteBuffer);
		}
	}

	public void flush() throws IOException {
		if(bufferList.size()!=0 || lastByteBuffer!=null) {
			handler.registerWrite();
		} else {
			return;
		}
		
		while(bufferList.size()>=5) {
			handler.waitTillFullyWritten();		
		}
	}

	public synchronized void write(int b) throws IOException {
		handler.isConnected();
		ByteBuffer byteBuffer = null;
		if(bufferList.size()!=0) {
			byteBuffer = (ByteBuffer) bufferList.remove(bufferList.size()-1);
			if(byteBuffer.remaining()==0) {
				bufferList.add(byteBuffer);
				byteBuffer = null;
			}
		}
		try {			
			if(byteBuffer==null) {
				byteBuffer = (ByteBuffer) handler.getServer().getByteBufferPool().borrowObject();
			}
		} catch(Exception e) {
			logger.warning("Could not borrow ByteBufer from pool: "+e);
			throw new IOException(e.toString());
		}
		byteBuffer.put((byte)b);
		bufferList.add(byteBuffer);
	}

	public void write(byte[] b) throws IOException {
		write(b, 0, b.length);
	}

	public synchronized void write(byte[] b, int off, int len) throws IOException {
		if(len==0) {
			return;
		}

		handler.isConnected();
		ByteBuffer byteBuffer = null;
		int remaining = 0;
		int toWrite = len;

		if(toWrite!=0 && bufferList.size()!=0) {
			byteBuffer = (ByteBuffer) bufferList.remove(bufferList.size()-1);
			if(byteBuffer.remaining()==0) {
				bufferList.add(byteBuffer);
				byteBuffer = null;
			}
		}

		while(toWrite!=0) {
			try {
				if(byteBuffer==null) {
					byteBuffer = (ByteBuffer) 
						handler.getServer().getByteBufferPool().borrowObject();	
				}
			} catch(Exception e) {
				logger.warning("Could not borrow ByteBufer from pool: "+e);
				throw new IOException(e.toString());
			}

			remaining = byteBuffer.remaining();
			if(remaining < toWrite) {
				byteBuffer.put(b, off, remaining);
				off = off + remaining;

				toWrite = toWrite - remaining;				
			} else {
				byteBuffer.put(b, off, toWrite);
				toWrite=0;
			}
			bufferList.add(byteBuffer);
			byteBuffer = null;
		}
	}

	//returns flag indicating if full write was done
	public synchronized boolean writeAllByteBuffer() throws IOException {
		if(lastByteBuffer!=null) {
			writeLastByteBuffer();
			if(lastByteBuffer!=null) return false;
		}

		if(bufferList.size()==0) {
			if(toNotify!=null) {
				synchronized(toNotify) {
					toNotify.notify();
					toNotify = null;
				}
			}
			return true;
		}

		while(bufferList.size()!=0) {
			lastByteBuffer = (ByteBuffer) bufferList.remove(0);
			lastByteBuffer.flip();
			writeLastByteBuffer();						
			if(lastByteBuffer != null) return false;
		}

		if(toNotify!=null) {
			synchronized(toNotify) {
				toNotify.notify();
				toNotify = null;
			}
		}
		return true;
	}

	private synchronized void writeLastByteBuffer() throws IOException {
		int written = 0;
		while(lastByteBuffer.remaining()!=0) {
			java.nio.channels.SocketChannel sc = handler.getSocketChannel();
			if(sc!=null && sc.isOpen()) {
				written = sc.write(lastByteBuffer);
				if(written==0) {
					break;
				}
				if(logger.isLoggable(Level.FINEST)) { 
					logger.finest("Written "+written+" bytes");
				}
			} else {
				throw new IOException("SocketChannel was closed.");
			}
		}
		if(lastByteBuffer.remaining()==0) {
			returnBufferBack(lastByteBuffer);
			lastByteBuffer = null;
		}
	}

	private void returnBufferBack(ByteBuffer byteBuffer) {
		try {
			handler.getServer().getByteBufferPool().returnObject(byteBuffer);	
		} catch(Exception er) {
			logger.warning("Error while returning ByteBuffer to pool: "+er);
		}
	}

	public void forceNotify() {
		if(toNotify==null) return;
		synchronized(toNotify) {
			toNotify.notify();
			toNotify = null;
		}
	}

	public boolean isDataAvailableForWrite(Object toNotify) {
		if(lastByteBuffer!=null) {
			if(this.toNotify!=null) {
				throw new IllegalStateException("toNotify object was already set!");
			}
			this.toNotify = toNotify;
			return true;
		}
		if(bufferList.size()==0) {
			return false;
		} else {
			if(this.toNotify!=null) {
				throw new IllegalStateException("toNotify object was already set!");
			}
			this.toNotify = toNotify;
			return true;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -