电脑技术学习

使用Flash的XMLSocket与Servlet建立长连接(3,建立XMLSocketWriter类)

dn001

XMLSocket在向ServerSocket发送消息的时候,对每个消息最后都会附加/0作为消息的结束
为了更便于日后的编程,我们对该特点进行特殊处理,专门封装出一个XMLSocketWriter类来完成
而是这种机制对外不可见,即便别人不知道这种特点,只要使用这个专门的Writer类都可以完成
以下是XMLSocketWriter的代码,是从JDK1.4.2.08中的源代码中修改而来的。
/*
* @(#)BufferedWriter.java; 1.24 03/01/23
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.inet.io;

/**
* Write text to a character-output stream, buffering characters so as to
* provide for the efficient writing of single characters, arrays, and strings.
*
* <p> The buffer size may be specified, or the default size may be accepted.
* The default is large enough for most purposes.
*
* <p> A newLine() method is provided, which uses the platform's own notion of
* line separator as defined by the system property <tt>line.separator</tt>.
* Not all platforms use the newline character ('n') to terminate lines.
* Calling this method to terminate each output line is therefore preferred to
* writing a newline character directly.
*
* <p> In general, a Writer sends its output immediately to the underlying
* character or byte stream.; Unless prompt output is required, it is advisable
* to wrap a BufferedWriter around any Writer whose write() operations may be
* costly, such as FileWriters and OutputStreamWriters.; For example,
*
* <pre>
* PrintWriter out
*= new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
* </pre>
*
* will buffer the PrintWriter's output to the file.; Without buffering, each
* invocation of a print() method would cause characters to be converted into
* bytes that would then be written immediately to the file, which can be very
* inefficient.
*
* @see PrintWriter
* @see FileWriter
* @see OutputStreamWriter
*
* @version;;1.24, 03/01/23
* @author; Mark Reinhold
* @sinceJDK1.1
*/

import java.io.IOException;
import java.io.Writer;


/**
*
* <p>
* Title: XMLSocketWriter
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2006
* </p>
* <p>
* Company: INET
* </p>
*
* 该类从JDK1.4.2_08的BufferedWriter拷贝而来并稍加修改
*
* @author chenyankui
* @version 1.0
*/
public class XMLSocketWriter extends Writer
{
private Writer out;

private char cb[];

private int nChars, nextChar;

private static int defaultCharBufferSize = 8192;

/**
* Line separator string. This is the value of the line.separator property
* at the moment that the stream was created.
*/
private String lineSeparator;

/**
* Create a buffered character-output stream that uses a default-sized
* output buffer.
*
* @param out
*;A Writer
*/
public XMLSocketWriter(Writer out)
{
this(out, defaultCharBufferSize);
}

/**
* Create a new buffered character-output stream that uses an output buffer
* of the given size.
*
* @param out
*;A Writer
* @param sz
*;Output-buffer size, a positive integer
*
* @exception IllegalArgumentException
*;;;;;If sz is <= 0
*/
public XMLSocketWriter(Writer out, int sz)
{
super(out);

if(sz <= 0)
throw new IllegalArgumentException("Buffer size <= 0");

this.out = out;
cb = new char[sz];

nChars = sz;
nextChar = 0;

lineSeparator = System.getProperty("line.separator");
}

/** Check to make sure that the stream has not been closed */
private void ensureOpen() throws IOException
{
if(out == null)
throw new IOException("Stream closed");
}

/**
* Flush the output buffer to the underlying character stream, without
* flushing the stream itself. This method is non-private only so that it
* may be invoked by PrintStream.
*/
void flushBuffer() throws IOException
{
synchronized(lock)
{
ensureOpen();

if(nextChar == 0)
{
return;
}

// 写http-head结束标记
out.write(MMFlash.HTTP_HEAD_END);

out.write(cb, 0, nextChar);

nextChar = 0;
}
}

/**
* Write a single character.
*
* @exception IOException
*;;;;;If an I/O error occurs
*/
public void write(int c) throws IOException
{
synchronized(lock)
{
ensureOpen();
if(nextChar >= nChars)
flushBuffer();

cb[nextChar++] = (char)c;
}
}

/**
* Our own little min method, to avoid loading java.lang.Math if we've run
* out of file descriptors and we're trying to print a stack trace.
*/
private int min(int a, int b)
{
if(a < b)
return a;

return b;
}

/**
* Write a portion of an array of characters.
*
* <p>
* Ordinarily this method stores characters from the given array into this
* stream's buffer, flushing the buffer to the underlying stream as needed.
* If the requested length is at least as large as the buffer, however, then
* this method will flush the buffer and write the characters directly to
* the underlying stream. Thus redundant <code>BufferedWriter</code>s
* will not copy data unnecessarily.
*
* @param cbuf
*;A character array
* @param off
*;Offset from which to start reading characters
* @param len
*;Number of characters to write
*
* @exception IOException
*;;;;;If an I/O error occurs
*/
public void write(char cbuf[], int off, int len) throws IOException
{
synchronized(lock)
{
ensureOpen();
if((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0))
{
throw new IndexOutOfBoundsException();
}
else if(len == 0)
{
return;
}
if(len >= nChars)
{
/*
* If the request length exceeds the size of the output buffer,
* flush the buffer and then write the data directly. In this
* way buffered streams will cascade harmlessly.
*/
flushBuffer();

out.write(cbuf, off, len);

return;
}

int b = off, t = off + len;

while(b < t)
{
int d = min(nChars - nextChar, t - b);

System.arraycopy(cbuf, b, cb, nextChar, d);

b += d;
nextChar += d;

if(nextChar >= nChars)
flushBuffer();
}
}
}

/**
* Write a portion of a String.
*
* @param s
*;String to be written
* @param off
*;Offset from which to start reading characters
* @param len
*;Number of characters to be written
*
* @exception IOException
*;;;;;If an I/O error occurs
*/
public void write(String s, int off, int len) throws IOException
{
synchronized(lock)
{
ensureOpen();

int b = off, t = off + len;

while(b < t)
{
int d = min(nChars - nextChar, t - b);
s.getChars(b, b + d, cb, nextChar);

b += d;
nextChar += d;

if(nextChar >= nChars)
flushBuffer();
}
}
}

/**
* Write a line separator. The line separator string is defined by the
* system property <tt>line.separator</tt>, and is not necessarily a
* single newline ('n') character.
*
* @exception IOException
*;;;;;If an I/O error occurs
*/
public void newLine() throws IOException
{
write(lineSeparator);
}

/**
* Flush the stream.
*
* @exception IOException
*;;;;;If an I/O error occurs
*/
public void flush() throws IOException
{
synchronized(lock)
{
if(nextChar == 0)
{
return;
}

// 写数据结束标记
this.write(MMFlash.HTTP_DATA_END);

flushBuffer();

out.flush();
}
}

/**
* Close the stream.
*
* @exception IOException
*;;;;;If an I/O error occurs
*/
public void close() throws IOException
{
synchronized(lock)
{
if(out == null)
return;

flushBuffer();

out.close();
out = null;
cb = null;
}
}
}