📄 tdscomm.java
字号:
}
}
/*
* Stefan Bodewig 2000-06-21
*
* removed appendString() to keep the encoding to and from the
* server charset in on place - i.e. Tds.
*
* It had to be Tds as we need to specify the length for the
* String as well, sometimes before we send the actual data,
* sometimes after we've sent them.
*
* If we need to know the length beforehand in Tds, we'd have to
* convert the data twice, once to get the length and once to send
* them.
*/
// public void appendString(
// String s,
// int length,
// byte pad)
// throws java.io.IOException
// {
// int i;
// byte dst[];
//
//
// dst = encoder.getBytes(s.substring(0, (length<=s.length() ? length
// : s.length())));
//
// for(i=0; i<dst.length; i++)
// {
// appendByte(dst[i]);
// }
//
// for(; i<length; i++)
// {
// appendByte(pad);
// }
// }
/**
* Send the logical packet. <p>
*
* Send the logical packet the has been constructed.
*
*@exception java.io.IOException @todo Description of Exception
*/
public synchronized void sendPacket()
throws java.io.IOException
{
sendPhysicalPacket( true );
nextOutBufferIndex = 0;
packetType = 0;
notify();
}
/**
* store a byte of data at a particular location in the outBuffer.
*
*@param index position in outBuffer to store data
*@param value value to store in the outBuffer.
*/
private void storeByte(
int index,
byte value )
{
outBuffer[index] = value;
}
/**
* store a short integer of data at a particular location in the outBuffer.
*
*@param index position in outBuffer to store data
*@param s @todo Description of Parameter
*/
private void storeShort(
int index,
short s )
{
outBuffer[index] = ( byte ) ( ( s >> 8 ) & 0xff );
outBuffer[index + 1] = ( byte ) ( ( s >> 0 ) & 0xff );
}
/**
* send the data in the outBuffer. <p>
*
* Fill in the TDS packet header data and send the data in outBuffer to the
* DB server.
*
*@param isLastSegment is this the last physical packet that
* makes up the physical packet?
*@exception java.io.IOException @todo Description of Exception
*/
private void sendPhysicalPacket( boolean isLastSegment )
throws java.io.IOException
{
if ( nextOutBufferIndex > headerLength
|| packetType == CANCEL ) {
// packet type
storeByte( 0, ( byte ) ( packetType & 0xff ) );
storeByte( 1, isLastSegment ? ( byte ) 1 : ( byte ) 0 );
storeShort( 2, ( short ) nextOutBufferIndex );
storeByte( 4, ( byte ) 0 );
storeByte( 5, ( byte ) 0 );
storeByte( 6, ( byte ) ( tdsVer == TDS70 ? 1 : 0 ) );
storeByte( 7, ( byte ) 0 );
out.write( outBuffer, 0, nextOutBufferIndex );
packetsSent++;
if ( Logger.isActive() ) {
String dump = HexDump.hexDump( outBuffer, nextOutBufferIndex );
String t = ( new Timestamp(
System.currentTimeMillis() ) ).toString();
Logger.println( "Instance " + id + " @ " + t
+ " sent packet #" + packetsSent + "\n" + dump );
}
}
}
/**
* peek at the next byte of data. <p>
*
* This returns the next byte of data that would be returned by getByte(),
* but does not actually consume the data. <b>Note-</b> We can't
* synchronize this method (or most of the other methods in this class)
* because of the way cancels are handled. If a thread is waiting for a
* response from the server the cancelController class must be able to call
* sendPacket() to cancel the request.
*
*@return The next byte of data
* that will be returned by getByte()
*@exception net.sourceforge.jtds.jdbc.TdsException
*@exception java.io.IOException
*/
public byte peek()
throws net.sourceforge.jtds.jdbc.TdsException, java.io.IOException
{
// If out of data, read another physical packet.
if( inBufferIndex >= inBufferLen )
getPhysicalPacket();
return inBuffer[inBufferIndex];
}
/**
* read a byte of data from the DB server. <p>
*
* This will return the next byte of data from the DB server. <p>
*
* <B>Warning</B> If there is not data available this method will block.
*
*@return The Byte value
*@exception net.sourceforge.jtds.jdbc.TdsException @todo Description of
* Exception
*@exception java.io.IOException @todo Description of
* Exception
*/
public byte getByte()
throws net.sourceforge.jtds.jdbc.TdsException,
java.io.IOException
{
byte result;
if ( inBufferIndex >= inBufferLen ) {
// out of data, read another physical packet.
getPhysicalPacket();
}
result = inBuffer[inBufferIndex++];
return result;
}
/**
* Reads and returns <code>len</code> bytes. If <code>exclusiveBuffer</code>
* is <code>true</code>, a new buffer of that size will be allocated.
* Otherwise, {@link resBuffer} will be used. Note that in this second case
* the returned buffer will very likely have a larger size than the
* number of bytes requested.
*/
public byte[] getBytes(int len, boolean exclusiveBuffer)
throws net.sourceforge.jtds.jdbc.TdsException, java.io.IOException
{
byte result[] = null;
int i;
// Do not keep an internal result buffer larger than 16k.
// This would unnecessarily use up memory.
if( exclusiveBuffer || len>16384 )
result = new byte[len];
else
{
if( resBuffer.length < len )
resBuffer = new byte[len];
result = resBuffer;
}
for( i=0; i<len; )
{
if( inBufferIndex >= inBufferLen )
getPhysicalPacket();
int avail = inBufferLen - inBufferIndex;
avail = avail>len-i ? len-i : avail;
System.arraycopy(inBuffer, inBufferIndex, result, i, avail);
i += avail;
inBufferIndex += avail;
}
return result;
}
/**
* Reads bytes or characters (depending on TDS version) and constructs a
* string with them. Sybase will let the client choose byte ordering, but
* SQLServer 7.0 wants little endian only. In the interest of simplicity,
* just use little endian regardless of the type of server. Added
* 2000-06-05.
*
*@param len @todo Description of
* Parameter
*@return The String value
*@exception net.sourceforge.jtds.jdbc.TdsException @todo Description of
* Exception
*@exception java.io.IOException @todo Description of
* Exception
*/
public String getString( int len )
throws net.sourceforge.jtds.jdbc.TdsException,
java.io.IOException
{
if ( tdsVer == TDS70 ) {
char[] chars = new char[len];
for ( int i = 0; i < len; ++i ) {
int lo = getByte() & 0xFF;
int hi = getByte() & 0xFF;
chars[i] = ( char ) ( lo | ( hi << 8 ) );
}
return new String( chars );
}
else {
return new String( getBytes(len, false), 0, len );
}
}
public void skip( int i )
throws net.sourceforge.jtds.jdbc.TdsException,
java.io.IOException
{
for ( ; i > 0; i-- ) {
getByte();
}
}
// skip()
public int getNetShort()
throws TdsException, java.io.IOException
{
byte tmp[] = new byte[2];
tmp[0] = getByte();
tmp[1] = getByte();
return ntohs( tmp, 0 );
}
public int getTdsShort()
throws net.sourceforge.jtds.jdbc.TdsException, java.io.IOException
{
int lo = ( ( int ) getByte() & 0xff );
int hi = ( ( int ) getByte() & 0xff ) << 8;
return lo | hi;
}
public int getTdsInt()
throws net.sourceforge.jtds.jdbc.TdsException, java.io.IOException
{
int result;
int b1 = ( ( int ) getByte() & 0xff );
int b2 = ( ( int ) getByte() & 0xff ) << 8;
int b3 = ( ( int ) getByte() & 0xff ) << 16;
int b4 = ( ( int ) getByte() & 0xff ) << 24;
result = b4 | b3 | b2 | b1;
return result;
}
public long getTdsInt64()
throws net.sourceforge.jtds.jdbc.TdsException, java.io.IOException
{
long b1 = ( ( long ) getByte() & 0xff );
long b2 = ( ( long ) getByte() & 0xff ) << 8;
long b3 = ( ( long ) getByte() & 0xff ) << 16;
long b4 = ( ( long ) getByte() & 0xff ) << 24;
long b5 = ( ( long ) getByte() & 0xff ) << 32;
long b6 = ( ( long ) getByte() & 0xff ) << 40;
long b7 = ( ( long ) getByte() & 0xff ) << 48;
long b8 = ( ( long ) getByte() & 0xff ) << 56;
return b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8;
}
/**
* Read a physical packet.<p>
* <B>Warning</B> This method will block until it gets all of the input.
* <p>
* <b>Note:</b> This method should not be synchronized (at least not on
* <code>this</code> object) because it would prevent us from sending
* CANCEL packets, which are sent asynchronously.
*
* @exception TdsException @todo Description of Exception
* @exception java.io.IOException @todo Description of Exception
*/
private void getPhysicalPacket()
throws TdsException, java.io.IOException
{
// read the header
for ( int nread = 0; nread < 8; ) {
nread += in.read( tmpBuf, nread, 8 - nread );
}
if ( Logger.isActive() ) {
String dump = net.sourceforge.jtds.util.HexDump.hexDump( tmpBuf, 8 );
String t = ( new Timestamp(
System.currentTimeMillis() ) ).toString();
Logger.println( "Instance " + id + " @ " + t
+ " received header #" + ( packetsReceived + 1 )
+ "\n" + dump );
}
byte packetType = tmpBuf[0];
if ( packetType != LOGON
&& packetType != QUERY
&& packetType != REPLY ) {
throw new TdsUnknownPacketType( packetType, tmpBuf );
}
// figure out how many bytes are remaining in this packet.
int len = ntohs( tmpBuf, 2 ) - 8;
// Added 2000-06-05
if ( len >= inBuffer.length ) {
inBuffer = new byte[len];
}
if ( len < 0 ) {
throw new TdsException( "Confused by a length of " + len );
}
// now get the data
for ( int nread = 0; nread < len; ) {
nread += in.read( inBuffer, nread, len - nread );
}
packetsReceived++;
// adjust the bookkeeping info about the incoming buffer
inBufferLen = len;
inBufferIndex = 0;
if ( Logger.isActive() ) {
String dump = net.sourceforge.jtds.util.HexDump.hexDump( inBuffer, len );
String t = ( new Timestamp(
System.currentTimeMillis() ) ).toString();
Logger.println( "Instance " + id + " @ " + t
+ " received data #" + ( packetsReceived )
+ "\n" + dump );
}
}
void resizeOutbuf( int newsize )
{
if ( newsize > outBufferLen ) {
byte[] newBuf = new byte[newsize];
System.arraycopy( outBuffer, 0, newBuf, 0, outBufferLen );
outBufferLen = newsize;
outBuffer = newBuf;
}
}
/**
* convert two bytes in a byte array into a Java short integer.
*
*@param buf array of data
*@param offset index into the buf array where the short integer is
* stored.
*@return @todo Description of the Returned Value
*/
private static int ntohs( byte buf[], int offset )
{
int lo = ( ( int ) buf[offset + 1] & 0xff );
int hi = ( ( ( int ) buf[offset] & 0xff ) << 8 );
return hi | lo;
// return an int since we really want an _unsigned_
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -