【发布时间】:2020-05-29 10:31:15
【问题描述】:
真正的重点是——我的 Android TLS/TCP 套接字有时会断开中间数据流。通常是由于超时等原因。我试图确定在套接字切断之前实际成功发送了多少数据,以便我知道从哪里获取。
我该怎么做?
我的想法是从套接字中拉出输出流,一次写一点。如果我们断开连接,那么我可以从中断处继续并继续发送下一个块。
我选择不使用 BufferedOutputStream,因为断开连接后我不确定发送了多少,没有发送多少。我很想弄错。
这是我最好的尝试:
/**
* Static class that holds the currently writable data
*/
final private class WritingByteArray {
/**
* Easy C-tor
*/
public WritingByteArray( final byte[] bytes ) {
this.bytes = bytes;
this.offset = 0;
}
/**
* Convenience
*/
public int length() {
return( bytes.length );
}
/**
* Convenience
*/
public int remaining( int max ) {
return( Math.min( max, length()-offset ) );
}
/**
* Consume bytes. Really just increment the offset with a safety catch
*/
private void consume( int size ) {
offset = Math.min( bytes.length, offset+size );
}
/**
* Remaining without a max
*/
public int remaining() {
return( length()-offset );
}
/**
* Are we empty?
*/
public boolean empty() {
return( offset>=length() );
}
public byte[] bytes; //!< The byte array we're working with
public int offset; //!< Our reading offset
}
/**
* Our write data function new
*/
private void writeDataNew() {
final int WRITE_BUFFER_SIZE = ( 8*1024 ); //!< 8kb of write buffer size
try {
OutputStream outputStream = sslSocket.getOutputStream();
// Do we have data we are currently writing
if( currentByteArray==null ) {
Log.d(
TAG,
"We don't have anything in the current byte array. Pulling from the output buffer."
);
// Pull from the outputBuffer
synchronized( outputBuffer ) {
final int size = outputBuffer.size();
Log.d( TAG, "OutputBuffer has "+size );
// This was one done outside of synchronization... that's bad!
if( size==0 ) {
Log.d( TAG, "Our output buffer is actually empty." );
return;
}
// Copy the bytes to our private byte array
currentByteArray = new WritingByteArray( outputBuffer.toByteArray() );
// Get the data
// outputStream.write( outputBuffer.toByteArray() );
// Reset the buffer
outputBuffer.reset();
} // Free the mutex so bytearray can be written again
}
// Now write the data
final int size = currentByteArray.remaining( WRITE_BUFFER_SIZE );
// Do we have bytes to send?
if( size>0 ) {
// Alert how much we'll write
Log.d( TAG, "We have "+size+" data to write" );
// Write our deduced size
outputStream.write( currentByteArray.bytes, currentByteArray.offset, size );
// Flush the output so we can block???
// DOES THIS BLOCK?
// If this blocks maybe this will work...
outputStream.flush();
// Just a log tag
Log.d( TAG, "Data wrote "+size+" bytes of data." );
// Now consume
currentByteArray.consume( size );
// Do we have any left?
if( currentByteArray.empty() ) {
Log.d( TAG, "Clearing currentByteArray" );
currentByteArray = null; // Clear it so we know
}
}
else {
Log.d( TAG, "No more data left " );
// Just in case
currentByteArray = null;
}
// Call again
writeDataNew();
}
catch( final Exception e ) {
e.printStackTrace();
reportError( e.getLocalizedMessage() );
// Here we can reconnect and send more data if we failed out
}
}
【问题讨论】:
-
定义“发送成功”。这是否意味着“被对等方接收”,或“排队到操作系统进行传输”?
-
这是个好问题。我支持“被同行接受”,但除非我问同行,否则我认为这可能是不可知的。