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

📄 tdscomm.java

📁 Java写的TDS协议(JDBC/ODBC)实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//
// Copyright 1998 CDS Networks, Inc., Medford Oregon
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. All advertising materials mentioning features or use of this software
//    must display the following acknowledgement:
//      This product includes software developed by CDS Networks, Inc.
// 4. The name of CDS Networks, Inc.  may not be used to endorse or promote
//    products derived from this software without specific prior
//    written permission.
//
// THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//


package net.sourceforge.jtds.jdbc;
import net.sourceforge.jtds.util.HexDump;
import net.sourceforge.jtds.util.Logger;

import java.io.*;
import java.net.*;
import java.sql.Timestamp;

/**
 *  Handle the communications for a Tds instance.
 *
 *@author     Craig Spannring
 *@author     Igor Petrovski
 *@created    14 September 2001
 *@version    $Id: TdsComm.java,v 1.1 2002/10/14 10:48:59 alin_sinpalean Exp $
 */
public class TdsComm implements TdsDefinitions {

    // in and out are the sockets used for all communication with the
    // server.
    private DataOutputStream out = null;
    private DataInputStream in = null;

    // outBuffer is used to construct the physical packets that will
    // be sent to the database server.
    byte outBuffer[];

    int outBufferLen;

    // nextOutBufferIndex is an index into outBuffer where the next
    // byte of data will be stored while constructing a packet.
    int nextOutBufferIndex = 0;

    // The type of the TDS packet that is being constructed
    // in outBuffer.
    int packetType = 0;

    // Place to store the incoming data from the DB server.
    byte inBuffer[];

    // index of next byte that will be 'read' from inBuffer
    int inBufferIndex = 0;

    // Total Number of bytes stored in inBuffer.  (The number includes bytes
    // that have been 'read' as well as bytes that still need to be 'read'.
    int inBufferLen = 0;

    // Track how many packets we have sent and received
    int packetsSent = 0;
    int packetsReceived = 0;

    // Added 2000-06-07.  Used to control TDS version-specific behavior.
    private int tdsVer = TDS42;

    /**
     *@todo    Does this need to be synchronized?
     */
    byte tmpBuf[] = new byte[8];

    /**
     * Buffer that will be used to return byte[] values by getByte(int, boolean)
     * to avoid allocating a new buffer each time if not necessary.
     */
    byte resBuffer[] = new byte[256];

    /**
     *  @todo Description of the Field
     */
    public final static String cvsVersion = "$Id: TdsComm.java,v 1.1 2002/10/14 10:48:59 alin_sinpalean Exp $";

    final static int headerLength = 8;

    //
    // The following constants are the packet types.
    //
    // They are the first databayte in the packet and
    // define the type of data in that packet.
    /**
     *  @todo Description of the Field
     */
    public final static byte QUERY = 1;
    /**
     *  @todo Description of the Field
     */
    public final static byte LOGON = 2;
    /**
     *  @todo Description of the Field
     */
    public final static byte PROC = 3;
    /**
     *  @todo Description of the Field
     */
    public final static byte REPLY = 4;
    /**
     *  @todo Description of the Field
     */
    public final static byte CANCEL = 6;
    /**
     *  @todo Description of the Field
     */
    public final static byte LOGON70 = 16;
    // Added 2000-06-05

    // The minimum packet length that a TDS implementation can support
    // is 512 bytes.  This implementation will not support packets longer
    // than 512.  This will simplify the connection negotiation.
    //
    // XXX Some future release of this driver should be modified to
    // negotiate longer packet sizes with the DB server.
    private final static int maxPacketLength = 512;

    // For debuging purposes it would be nice to uniquely identify each Tds
    // stream.  id will be a unique value for each instance of this class.
    private static int nextId = 0;

    private int id;

    public TdsComm( Socket sock, int tdsVer_ )
             throws java.io.IOException
    {
        out = new DataOutputStream( sock.getOutputStream() );
        in = new DataInputStream( sock.getInputStream() );

        outBufferLen = maxPacketLength;
        outBuffer = new byte[outBufferLen];
        inBuffer = new byte[maxPacketLength];

        // Added 2000-06-07
        tdsVer = tdsVer_;

        id = ++nextId;
    }


    public void close()
    {
        // nop for now.
    }


    /*
     *  private void clearInputStream() throws IOException
     *  {
     *  int leftOver = in.available();
     *  if (leftOver > 0) {
     *  byte[] tmpBuffer = new byte[leftOver];
     *  for (int tmpread = 0; tmpread < leftOver; )
     *  {
     *  int num = in.read(tmpBuffer, tmpread, leftOver - tmpread);
     *  if (num < 0) break;
     *  tmpread += num;
     *  }
     *  if (Logger.isActive())
     *  {
     *  String  dump = net.sourceforge.jtds.util.HexDump.hexDump(tmpBuffer, leftOver);
     *  String  t    = (new Timestamp(
     *  System.currentTimeMillis())).toString();
     *  Logger.println("Instance "  + id + " @ " + t
     *  + " recevied leftOver"
     *  + "\n" + dump);
     *  }
     *  }
     *  }
     */

    /**
     * Start a TDS packet. <br>
     * This method should be called to start a logical TDS packet.
     *
     * @param  type  Type of the packet. Can be QUERY, LOGON, PROC, REPLY, or
     *               CANCEL.
     */
    public synchronized void startPacket( int type ) throws TdsException
    {
        if( type!=CANCEL && inBufferIndex!=inBufferLen )
        {
            // SAfe It's ok to throw this exception so that we will know there
            //      is a design flaw somewhere, but we should empty the buffer
            //      however. Otherwise the connection will never close (e.g. if
            //      SHOWPLAN_ALL is ON, a resultset will be returned by commit
            //      or rollback and we will never get rid of it). It's true
            //      that we should find a way to actually process these packets
            //      but for now, just dump them (we have thrown an exception).
            inBufferIndex = inBufferLen;
            if( Logger.isActive() )
                Logger.println("Unprocessed data in input buffer. Dumping. ["+
                    inBufferIndex+"/"+inBufferLen+"]");
            throw new TdsException("Unprocessed data in input buffer.");
        }

        // Only one thread at a time can be building an outboudn packet.
        // This is primarily a concern with building cancel packets.
        //  XXX: as why should more than one thread work with the same tds-stream ??? would be fatal anyway
        while ( someThreadIsBuildingPacket() ) {
            try {
                wait();
            }
            catch ( java.lang.InterruptedException e ) {
                // nop
            }
        }

        packetType = type;
        nextOutBufferIndex = headerLength;
    }


    /**
     *  Is some thread currently building a logical TDS packet?
     *
     *@return    true iff a packet is being built.
     */
    public boolean someThreadIsBuildingPacket()
    {
        return packetType != 0;
    }


    /**
     *  append a byte onto the end of the logical TDS packet. <p>
     *
     *  Append a byte onto the end of the logical TDS packet. When a physical
     *  packet is full send it to the server.
     *
     *@param  b                        byte to add to the TDS packet
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendByte( byte b )
             throws java.io.IOException
    {
        if ( nextOutBufferIndex == outBufferLen ) {
            // If we have a full physical packet then ship it out to the
            // network.
            sendPhysicalPacket( false );
            nextOutBufferIndex = headerLength;
        }

        storeByte( nextOutBufferIndex, b );
        nextOutBufferIndex++;
    }
    // appendByte()


    /**
     *  append an array of bytes onto the end of the logical TDS packet.
     *
     *@param  b                        bytes to add to the TDS packet
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendBytes( byte[] b )
             throws java.io.IOException
    {
        appendBytes( b, b.length, ( byte ) 0 );
    }
    // appendBytes()



    /**
     *  append an array of bytes onto the end of the logical TDS packet.
     *
     *@param  b                        bytes to add to the TDS packet
     *@param  len                      maximum number of bytes to transmit
     *@param  pad                      fill with this byte until len is reached
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendBytes( byte[] b, int len, byte pad )
             throws java.io.IOException
    {
        int i = 0;
        for ( ; i < b.length && i < len; i++ ) {
            appendByte( b[i] );
        }
        for ( ; i < len; i++ ) {
            appendByte( pad );
        }
    }


    /**
     *  append a short int onto the end of the logical TDS packet. <p>
     *
     *
     *
     *@param  s                        short int to add to the TDS packet
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendShort( short s )
             throws java.io.IOException
    {
        appendByte( ( byte ) ( ( s >> 8 ) & 0xff ) );
        appendByte( ( byte ) ( ( s >> 0 ) & 0xff ) );
    }


    /**
     *  Appends a short int onto the end of the logical TDS packet. <p>
     *
     *
     *
     *@param  s                        short int to add to the TDS packet
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendTdsShort( short s )
             throws java.io.IOException
    {
        appendByte( ( byte ) ( ( s >> 0 ) & 0xff ) );
        appendByte( ( byte ) ( ( s >> 8 ) & 0xff ) );
    }


    /**
     *  append a Double onto the end of the logical TDS packet. <p>
     *
     *  Append the Double value onto the end of the TDS packet as a SYBFLT8.
     *
     *@param  value                    Double to add to the TDS packet
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendFlt8( Double value )
             throws java.io.IOException
    {
        long l = Double.doubleToLongBits( value.doubleValue() );

        appendByte( ( byte ) ( ( l >> 0 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 8 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 16 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 24 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 32 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 40 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 48 ) & 0xff ) );
        appendByte( ( byte ) ( ( l >> 56 ) & 0xff ) );
    }


    public void appendInt( int i )
             throws java.io.IOException
    {
        appendByte( ( byte ) ( ( i >> 24 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 16 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 8 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 0 ) & 0xff ) );
    }


    public void appendTdsInt( int i )
             throws java.io.IOException
    {
        appendByte( ( byte ) ( ( i >> 0 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 8 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 16 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 24 ) & 0xff ) );
    }


    public void appendInt64( long i )
             throws java.io.IOException
    {
        appendByte( ( byte ) ( ( i >> 56 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 48 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 40 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 32 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 24 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 16 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 8 ) & 0xff ) );
        appendByte( ( byte ) ( ( i >> 0 ) & 0xff ) );
    }


    /**
     *  Appends the 16-bit characters from the caller's string, without
     *  narrowing the characters. Sybase let's the client decide what byte order
     *  to use but it \ appears that SQLServer 7.0 little-endian byte order.
     *  Added 2000-06-05
     *
     *@param  s                        @todo Description of Parameter
     *@exception  java.io.IOException  @todo Description of Exception
     */
    public void appendChars( String s ) throws java.io.IOException
    {
        for ( int i = 0; i < s.length(); ++i ) {
            int c = s.charAt( i );
            byte b1 = ( byte ) ( c & 0xFF );
            byte b2 = ( byte ) ( ( c >> 8 ) & 0xFF );
            appendByte( b1 );
            appendByte( b2 );

⌨️ 快捷键说明

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