📄 streamconnector.java
字号:
/*---------------------------------------------------------------------------
* Copyright (C) 2001 Dallas Semiconductor Corporation, All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Dallas Semiconductor
* shall not be used except as stated in the Dallas Semiconductor
* Branding Policy.
*---------------------------------------------------------------------------
*/
package com.eta.etatcpcomm.server;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import com.eta.etatcpcomm.*;
/* This class connects a serial input stream to a network output stream OR
* connects a network input stream to a serial output stream. These are
* threads, so we start them a-runnin' and just let them spin, grabbing input
* then shooting it out the other side.
*/
public class StreamConnector extends Thread
{
public StreamConnector( InputStream src, OutputStream sink)
{
this.src = src;
this.sink = sink;
}
public void start()
{
setDaemon( true);
super.start();
if( DEBUG) System.out.println( "StreamConnector started.");
}
protected int readDataFromSrc( byte[] buf, int off, int len) throws IOException
{
return src.read( buf, off, len);
}
protected boolean isEOF( int b)
{
if( b == -1)
{
running = false;
return true;
}
return false;
}
public void transferData( int bytesToTransfer) throws IOException
{
while ((bytesToTransfer > 0) && running)
{
// Calculate bytes to read
int bytesToRead = Math.min( BUFSIZE, bytesToTransfer);
/*
DMS - changed this to only try to read if there is something available...
otherwise we just end up continuously notifying ourselves that we've
sent zero bytes across. this also fixes the problem where threads kept
sticking around...if there's nothing available we can still check to see
if we aren't still running (see the brand spankin' new 'running' boolean)
then we can bail...
*/
if (src.available() > 0)
{
int bytesRead = readDataFromSrc( buf, 0, bytesToRead);
if (bytesRead > 0)
{
if( isEOF( bytesRead))
{
if( DEBUG) System.out.println( Thread.currentThread().getName() + " done (EOF).");
return;
}
if( DEBUG) System.out.println( Thread.currentThread().getName() + " read " + bytesRead + " bytes.");
// Write out bytes
writeDataToSink( buf, 0, bytesRead);
// Decrement bytesToTransfer
bytesToTransfer -= bytesRead;
}
}
}
}
protected void writeDataToSink( byte[] buf, int off, int len) throws IOException
{
if( len > 0)
{
// Write out bytes
sink.write( buf, off, len);
// Flush bytes
/** @todo Verify that flush() is truly necessary */
sink.flush();
}
// Send notification that data has been written.
dataWritten( len);
}
// Provide the service.
public void run()
{
running = true;
while( !Thread.interrupted() && running)
{
try
{
transferData( BUFSIZE);
}
catch( IOException ioe)
{
// Abort
if( DEBUG) System.out.println( Thread.currentThread().getName() + " done (abort).");
return;
}
}
if( DEBUG) System.out.println( Thread.currentThread().getName() + " done " +
(Thread.interrupted() ? "(eof)." : "(interrupted).") );
}
/*
allows us to be 'interrupted' by another class...nothing in here should block and
we should always be checking to see if we are still alive, otherwise we get thread leakage!
*/
public void interrupt()
{
if( DEBUG) System.out.println(getName() + " INTERRUPT.");
running = false;
super.interrupt();
}
// This method exists soley for subclasses that need to know when
// data has been written to sink so they can, for example, inform
// the other end of sink that data is available or inform the other
// end of src that data has been written.
//
// The default implementation does nothing.
protected void dataWritten( int bytesWritten) {}
// This method returns src.available()
public int available() throws IOException
{
return src.available();
}
/*
DMS - increased the size of the buffer...I was having problems loading the firmware
through JavaKit, and I think the reason was because we were using really small chunks of data,
and some race condition existed where we hadn't yet gotten the data to write the firmware.
Loading the firmware used to fail 3 out of 4 times with CRC errors, now it is pretty
error free.
*/
public static final int BUFSIZE = 4096;
/*
DMS - this should not be a static byte array, especially if two thread are going
to talk to it and there are no synchronized blocks in here!
*/
protected byte[] buf = new byte[BUFSIZE];
protected InputStream src;
protected OutputStream sink;
boolean running = false;
protected static int objId = 0;
private static final boolean DEBUG = false;
static Object lock = new Object();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -