`
Donald_Draper
  • 浏览: 979863 次
社区版块
存档分类
最新评论

文件通道解析一(读写操作,通道数据传输等)

    博客分类:
  • NIO
nio 
阅读更多
Reference定义(PhantomReference,Cleaner):http://donald-draper.iteye.com/blog/2371661
FileChanne定义:http://donald-draper.iteye.com/blog/2374149
文件读写方式简单综述:http://donald-draper.iteye.com/blog/2374237
文件读写方式简单综述后续(文件,流构造):http://donald-draper.iteye.com/blog/2374294
文件通道创建方式综述:http://donald-draper.iteye.com/blog/2374537
引言:
     获取区文件的通道一共有四种,第一种从FileOutputStream获取写模式文件通道,第二种从FileInputStream获取读模式文件通道,第三种从RandomAccessFile获取读写模式文件通道,第四种调用FileChannelImpl#open方法,这个过程首先从参数文件Path(WindowsPath)获取文件系统的提供者,实际为WindowsFileSystemProvider,委托给WindowsFileSystemProvider创建文件通道,WindowsFileSystemProvider根据WindowsPath和,文件属性WindowsSecurityDescriptor(FileAttribute[]),和打开选项集,将实际创建通道任务交给WindowsChannelFactory,WindowsChannelFactory首先将打开选项装换为内部的通道配置标志Flags(读写模式(read,writer),同步方式(sync,dsync),append等),然后根据Flags,和Path信息等信息创建文件,创建文件实际由WindowsNativeDispatcher完成。WindowsNativeDispatcher首先从线程本地缓存获取NativeBuffer,将Path信息放在NativeBuffer中,然后创建文件,创建后,将NativeBuffer释放,即放入线程本地缓存,以便重用。具体选择哪种方式,根据需要选择。
从今天开始,文件通道的具体实现FileChanneImpl
public class FileChannelImpl extends FileChannel
{
 private static final long allocationGranularity = initIDs();
    private final FileDispatcher nd;//文件分发器
    private final FileDescriptor fd;//文件描述
    private final boolean writable;//通道是否可写
    private final boolean readable;//通道是否可读
    private final boolean append;//通道写是否为追加模式
    private final Object parent;//创建通道的对象
    //下面这些属性,暂时不能确定是具体什么意思,只能先从字面上去理解,
    //这里我们先放在这里,后面用到在讲
    private final NativeThreadSet threads = new NativeThreadSet(2);
    private final Object positionLock = new Object();//文件读写是位置锁
    private static volatile boolean transferSupported = true;//是否支持通道传输
    private static volatile boolean pipeSupported = true;//是否支持管道
    private static volatile boolean fileSupported = true;//是否支持文件
    private static final long MAPPED_TRANSFER_SIZE = 8388608L;/
    private static final int TRANSFER_SIZE = 8192;
    private static final int MAP_RO = 0;
    private static final int MAP_RW = 1;
    private static final int MAP_PV = 2;
    private volatile FileLockTable fileLockTable;//存放文件锁的Table
    private static boolean isSharedFileLockTable;//文件锁table是否为共享
    private static volatile boolean propertyChecked;
    static final boolean $assertionsDisabled = !sun/nio/ch/FileChannelImpl.desiredAssertionStatus();

    static 
    {
        //加载nio,net资源库
        Util.load();
    }
     private static native long initIDs();
 }

来看构造
 public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, Object obj)
    {
        return new FileChannelImpl(filedescriptor, flag, flag1, false, obj);
    }

    public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj)
    {
        return new FileChannelImpl(filedescriptor, flag, flag1, flag2, obj);
    }
    //创建FileChannelImpl
    private FileChannelImpl(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj)
    {
        fd = filedescriptor;
        readable = flag;
        writable = flag1;
        append = flag2;
        parent = obj;
        nd = new FileDispatcherImpl(flag2);
    }

从上面可以看出文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器
FileDispatcherImpl。
public int write(ByteBuffer bytebuffer)
        throws IOException
    {
        ensureOpen();//确保通道打开
        if(!writable)//如果通道不可写,则抛出不可写异常
            throw new NonWritableChannelException();
        Object obj = positionLock;//获取position锁
        JVM INSTR monitorenter ;//进入同步
        int i;
        int j;
        i = 0;
        j = -1;
        int k;
        begin();
	...
        j = threads.add();
	//看到这里是不是很熟悉,在socketChannel和DatagramChannel都有讲过,这里不再讲
	//只不过nd为FileDispatcherImpl
        do
            i = IOUtil.write(fd, bytebuffer, -1L, nd, positionLock);
        while(i == -3 && isOpen());
	...
    }
    
    public long write(ByteBuffer abytebuffer[], int i, int j)
        throws IOException
    {
        if(i < 0 || j < 0 || i > abytebuffer.length - j)
            throw new IndexOutOfBoundsException();
        ensureOpen();
        if(!writable)
            throw new NonWritableChannelException();
        Object obj = positionLock;
        JVM INSTR monitorenter ;
        ...
	//看到这里是不是很熟悉,在socketChannel和DatagramChannel都有讲过,这里不再讲
	//只不过nd为FileDispatcherImpl
        do
            l = IOUtil.write(fd, abytebuffer, i, j, nd);
        while(l == -3L && isOpen());
	...
}
public int read(ByteBuffer bytebuffer)
        throws IOException
    {
        ensureOpen();
        if(!readable)
            throw new NonReadableChannelException();
        Object obj = positionLock;
        JVM INSTR monitorenter ;
        int i;
        int j;
        i = 0;
        j = -1;
        int k;
        ...
	//看到这里是不是很熟悉,在socketChannel和DatagramChannel都有讲过,这里不再讲
	//只不过nd为FileDispatcherImpl
        do
            i = IOUtil.read(fd, bytebuffer, -1L, nd, positionLock);
        while(i == -3 && isOpen());
	...
}
 public long read(ByteBuffer abytebuffer[], int i, int j)
        throws IOException
    {
        if(i < 0 || j < 0 || i > abytebuffer.length - j)
            throw new IndexOutOfBoundsException();
        ensureOpen();
        if(!readable)
            throw new NonReadableChannelException();
        Object obj = positionLock;
        JVM INSTR monitorenter ;
        ...
        do
            l = IOUtil.read(fd, abytebuffer, i, j, nd);
        while(l == -3L && isOpen());
       ...
    }

从上面可以看出文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成完成,这一点和SocketChannel通道思路相似。
public long transferTo(long l, long l1, WritableByteChannel writablebytechannel)
        throws IOException
    {
        ensureOpen();//确保当前通道打开
        if(!writablebytechannel.isOpen())//如果目的通道,不可写则抛出ClosedChannelException
            throw new ClosedChannelException();
        if(!readable)//如果当前通道不可读,则抛出NonReadableChannelException
            throw new NonReadableChannelException();
	//如果目的通道为FileChannelImpl,且不可写,则抛出NonWritableChannelException
        if((writablebytechannel instanceof FileChannelImpl) && !((FileChannelImpl)writablebytechannel).writable)
            throw new NonWritableChannelException();
        if(l < 0L || l1 < 0L)//检查position和count参数
            throw new IllegalArgumentException();
	//获取当前文件通道size
        long l2 = size();
        if(l > l2)//如果position大于当前文件size,返回0
            return 0L;
        int i = (int)Math.min(l1, 2147483647L);//获取需要读取字节数,为count参数和2^31-1当中的最小的一个
        if(l2 - l < (long)i)
            i = (int)(l2 - l);//需要读取的字节数
        long l3;
        if((l3 = transferToDirectly(l, i, writablebytechannel)) >= 0L)
            return l3;
        if((l3 = transferToTrustedChannel(l, i, writablebytechannel)) >= 0L)
            return l3;
        else
            return transferToArbitraryChannel(l, i, writablebytechannel);
    }

transferTo方法有3点要关注
1
if((l3 = transferToDirectly(l, i, writablebytechannel)) >= 0L)
    return l3;

private long transferToDirectly(long l, int i, WritableByteChannel writablebytechannel)
        throws IOException
    {
        int j;
        int k;
        long l1;
        int i1;
        if(!transferSupported)//不支持通道传输,
            return -4L;
        FileDescriptor filedescriptor = null;
	//这一段的目的就是获取目的通道文件描述符
        if(writablebytechannel instanceof FileChannelImpl)
        {
            if(!fileSupported)//如果通道为文件通道,但不支持文件
                return -6L;
            filedescriptor = ((FileChannelImpl)writablebytechannel).fd;
        } else
        if(writablebytechannel instanceof SelChImpl)
        {
	    //如果目的通道为SinkChannelImpl,且不支持管道
            if((writablebytechannel instanceof SinkChannelImpl) && !pipeSupported)
                return -6L;
            filedescriptor = ((SelChImpl)writablebytechannel).getFD();
        }
        if(filedescriptor == null)
            return -4L;
        j = IOUtil.fdVal(fd);//获取当前文件通道文件描述符的值
        k = IOUtil.fdVal(filedescriptor);//获取目的通道文件描述符的值
        if(j == k)//当前通道与目的通道相同
            return -4L;
        ...
        do
            l1 = transferTo0(j, l, i, k);
        while(l1 == -3L && isOpen());
        ...
    }
    private native long transferTo0(int i, long l, long l1, int j);

2.
if((l3 = transferToTrustedChannel(l, i, writablebytechannel)) >= 0L)
    return l3;

private long transferToTrustedChannel(long l, long l1, WritableByteChannel writablebytechannel)
        throws IOException
    {
        boolean flag;
        long l2;
	//判断目的通道是否为可选择通道,及socketChannel或DatagramChannel,Pipe(sink,source)
        flag = writablebytechannel instanceof SelChImpl;
	//如果目的通道不是文件通道也不是可选择通道,则返回
        if(!(writablebytechannel instanceof FileChannelImpl) && !flag)
            return -4L;
        l2 = l1;
_L2:
        long l3;
        if(l2 <= 0L)
            break; /* Loop/switch isn't completed */
        l3 = Math.min(l2, 8388608L);//获取读取的size,为count和2^23中间小的一个
	//将当前文件通达映射到内存中
        MappedByteBuffer mappedbytebuffer = map(java.nio.channels.FileChannel.MapMode.READ_ONLY, l, l3);
        int i;
	//直接调用目的通道的write方法将映射文件内存写到通道中。
        i = writablebytechannel.write(mappedbytebuffer);
        if(!$assertionsDisabled && i < 0)
            throw new AssertionError();
        l2 -= i;
        if(flag)
        {
	    //如果目的通道非文件通道,则释放文件通道映射内存空间
            unmap(mappedbytebuffer);
            break; /* Loop/switch isn't completed */
        }
        ...
   }

   再来看将通道数据映射到内存和释放映射内存空间
  
 //将通道数据映射到内存
     public MappedByteBuffer map(java.nio.channels.FileChannel.MapMode mapmode, long l, long l1)
        throws IOException
    {
     ...
      mappedbytebuffer = Util.newMappedByteBufferR(0, 0L, j, null);
      ...
    }
    //释放映射内存空间
     private static void unmap(MappedByteBuffer mappedbytebuffer)
    {
        Cleaner cleaner = ((DirectBuffer)mappedbytebuffer).cleaner();
        if(cleaner != null)
            cleaner.clean();
    }

3.
else
    return transferToArbitraryChannel(l, i, writablebytechannel);

private long transferToArbitraryChannel(long l, int i, WritableByteChannel writablebytechannel)
        throws IOException
    {
        ByteBuffer bytebuffer;
        long l1;
        long l2;
        int j = Math.min(i, 8192);
	//从线程缓存获取临时DirectByteBuffer
        bytebuffer = Util.getTemporaryDirectBuffer(j);
        l1 = 0L;
        l2 = l;
        long l3;
        Util.erase(bytebuffer);
        do
        {
            if(l1 >= (long)i)
                break;
            bytebuffer.limit(Math.min((int)((long)i - l1), 8192));
            int k = read(bytebuffer, l2);
            if(k <= 0)
                break;
            bytebuffer.flip();
	    //调用目的通道的写操作,直接写临时DirectByteBuffer
            int i1 = writablebytechannel.write(bytebuffer);
            l1 += i1;
            if(i1 != k)
                break;
            l2 += i1;
            bytebuffer.clear();
        } while(true);
        l3 = l1;
        Util.releaseTemporaryDirectBuffer(bytebuffer);
        return l3;
        ...
    }
  

从上面可以看出文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
再看文件通道传输方法transferFrom
 public long transferFrom(ReadableByteChannel readablebytechannel, long l, long l1)
        throws IOException
    {
        ensureOpen();//确保当前通道打开
        if(!readablebytechannel.isOpen())//确保源通道打开
            throw new ClosedChannelException();
        if(!writable)//如果当前通道不可写
            throw new NonWritableChannelException();
        if(l < 0L || l1 < 0L)//检查postion和count参数
            throw new IllegalArgumentException();
        if(l > size())//位置大于当前文件size,则直接返回
            return 0L;
	 //如果源通道为文件通道
        if(readablebytechannel instanceof FileChannelImpl)
            return transferFromFileChannel((FileChannelImpl)readablebytechannel, l, l1);
	//其他可读通道
        else
            return transferFromArbitraryChannel(readablebytechannel, l, l1);
    }

这个方法我们需要关注2点
1.
//如果源通道为文件通道
  if(readablebytechannel instanceof FileChannelImpl)
      return transferFromFileChannel((FileChannelImpl)readablebytechannel, l, l1);


private long transferFromFileChannel(FileChannelImpl filechannelimpl, long l, long l1)
        throws IOException
    {
        if(!filechannelimpl.readable)
            throw new NonReadableChannelException();
        Object obj = filechannelimpl.positionLock;
        JVM INSTR monitorenter ;
        long l2;
        long l3;
        long l4;
        long l5;
        l2 = filechannelimpl.position();
        l3 = Math.min(l1, filechannelimpl.size() - l2);
        l4 = l3;
        l5 = l2;
_L2:
        MappedByteBuffer mappedbytebuffer;
        if(l4 <= 0L)
            break; /* Loop/switch isn't completed */
        long l6 = Math.min(l4, 8388608L);
	//将源通道数据映射到内存
        mappedbytebuffer = filechannelimpl.map(java.nio.channels.FileChannel.MapMode.READ_ONLY, l5, l6);
	//委托writer方法
        long l8 = write(mappedbytebuffer, l);
        if(!$assertionsDisabled && l8 <= 0L)
            throw new AssertionError();
        l5 += l8;
        l += l8;
        l4 -= l8;
        unmap(mappedbytebuffer);
        if(true) goto _L2; else goto _L1
        IOException ioexception;
        ioexception;
        if(l4 == l3)
            throw ioexception;
	//读完,则释放通道映射内存
        unmap(mappedbytebuffer);
          goto _L1
        Exception exception;
        exception;
        unmap(mappedbytebuffer);
        throw exception;
_L1:
        long l7;
        l7 = l3 - l4;
	//未读完移动源通道的position
        filechannelimpl.position(l2 + l7);
        return l7;
        Exception exception1;
        exception1;
        throw exception1;
    }

再来看
//委托writer方法
long l8 = write(mappedbytebuffer, l);

public int write(ByteBuffer bytebuffer, long l)
        throws IOException
    {
        ...
	//这段代码又来了,不过此处的nd,为FileDispatcherImpl,与SocketDispatcher没有太多的区别
	只不过多了几个turncate和force等方法而已
        do
            i = IOUtil.write(fd, bytebuffer, l, nd, positionLock);
        while(i == -3 && isOpen());
       ...
    }

//IOUtil
 static int write(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj)
        throws IOException
    {
        ...
        int i1 = writeFromNativeBuffer(filedescriptor, bytebuffer1, l, nativedispatcher, obj);
        ...
    }

    private static int writeFromNativeBuffer(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj)
        throws IOException
    {
       ...
        if(l != -1L)
            i1 = nativedispatcher.pwrite(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k, l, obj);
        else
            i1 = nativedispatcher.write(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k);
        if(i1 > 0)
            bytebuffer.position(i + i1);
        return i1;
    }

//FileDispatcherImpl
class FileDispatcherImpl extends FileDispatcher
{
   ...
    //这一部分,没有什么好说的,看看就行
  int write(FileDescriptor filedescriptor, long l, int i)
        throws IOException
    {
        return write0(filedescriptor, l, i, append);
    }
     static native int write0(FileDescriptor filedescriptor, long l, int i, boolean flag)
        throws IOException;

    int pwrite(FileDescriptor filedescriptor, long l, int i, long l1, Object obj)
        throws IOException
    {
        Object obj1 = obj;
        JVM INSTR monitorenter ;
        return pwrite0(filedescriptor, l, i, l1);
        Exception exception;
        exception;
        throw exception;
    }
    static native int pwrite0(FileDescriptor filedescriptor, long l, int i, long l1)
        throws IOException;
   ...
}

2.其他可读通道
 else
      return transferFromArbitraryChannel(readablebytechannel, l, l1);

private long transferFromArbitraryChannel(ReadableByteChannel readablebytechannel, long l, long l1)
        throws IOException
    {
        ByteBuffer bytebuffer;
        long l2;
        long l3;
        int i = (int)Math.min(l1, 8192L);
        bytebuffer = Util.getTemporaryDirectBuffer(i);
        l2 = 0L;
        l3 = l;
        long l4;
        Util.erase(bytebuffer);
        do
        {
            if(l2 >= l1)
                break;
            bytebuffer.limit((int)Math.min(l1 - l2, 8192L));
	    //从源通道读取数据到临时DirectByteBuffer
            int j = readablebytechannel.read(bytebuffer);
            if(j <= 0)
                break;
            bytebuffer.flip();
	    //委托write,写DirectByteBuffer,即由IOUtil协助FileDispatcherImpl完成
            int k = write(bytebuffer, l3);
            l2 += k;
            if(k != j)
                break;
            l3 += k;
            bytebuffer.clear();
        } while(true);
        l4 = l2;
        Util.releaseTemporaryDirectBuffer(bytebuffer);
        ...
    }

从上面可以看出文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer
写入当前通道。
再来看force操作:
 
public void force(boolean flag)
        throws IOException
    {
       ...
        do
            i = nd.force(fd, flag);
        while(i == -3 && isOpen());
       ...
    }

//FileDispatcherImpl
int force(FileDescriptor filedescriptor, boolean flag)
        throws IOException
    {
        return force0(filedescriptor, flag);
    }
static native int force0(FileDescriptor filedescriptor, boolean flag)
        throws IOException;

再来看truncate方法
 public FileChannel truncate(long l)
        throws IOException
    {
        ...
        do
            i = nd.truncate(fd, l);
        while(i == -3 && isOpen());
        ...
    }

//FileDispatcherImpl
int truncate(FileDescriptor filedescriptor, long l)
        throws IOException
    {
        return truncate0(filedescriptor, l);
    }
static native int truncate0(FileDescriptor filedescriptor, long l)
        throws IOException;

再来看其他函数
//返回通道当前位置
 public long position()
        throws IOException
    {
        ...
	//append模式,则为文件尾,否则为文件头
        do
            l = append ? nd.size(fd) : position0(fd, -1L);
        while(l == -3L && isOpen());
        ...
    }
 //定位postion到位置l
 public FileChannel position(long l)
        throws IOException
    {
       ...
        do
            l1 = position0(fd, l);
        while(l1 == -3L && isOpen());
        ...
    }

private native long position0(FileDescriptor filedescriptor, long l);

//获取通道当前size
public long size()
        throws IOException
    {
        ...
        do
            l = nd.size(fd);
        while(l == -3L && isOpen());
       ...
    }

//FileDispatcherImpl
long size(FileDescriptor filedescriptor)
        throws IOException
    {
        return size0(filedescriptor);
    }
static native long size0(FileDescriptor filedescriptor)
        throws IOException;


总结:
   文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器,FileDispatcherImpl。
    文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成,这一点和SocketChannel通道读写思路基本相同。
    文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
     文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer
写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer写入当前通道。

文件通道解析二(文件锁,关闭通道):http://donald-draper.iteye.com/blog/2374736
附:
//FileDispatcher
abstract class FileDispatcher extends NativeDispatcher
{
    FileDispatcher()
    {
    }
    abstract int force(FileDescriptor filedescriptor, boolean flag)
        throws IOException;
    abstract int truncate(FileDescriptor filedescriptor, long l)
        throws IOException;
    abstract long size(FileDescriptor filedescriptor)
        throws IOException;
    abstract int lock(FileDescriptor filedescriptor, boolean flag, long l, long l1, boolean flag1)
        throws IOException;
    abstract void release(FileDescriptor filedescriptor, long l, long l1)
        throws IOException;
    abstract FileDescriptor duplicateForMapping(FileDescriptor filedescriptor)
        throws IOException;
    public static final int NO_LOCK = -1;
    public static final int LOCKED = 0;
    public static final int RET_EX_LOCK = 1;
    public static final int INTERRUPTED = 2;
}


0
1
分享到:
评论

相关推荐

    BMP文件格式和读写操作

    源代码通常会涉及文件流操作、内存映射以及位操作等技术。 7. **应用与扩展** BMP文件格式简单直观,适合教学和实验。然而,由于其未压缩的特点,文件体积较大,不适合网络传输或存储。在实际应用中,更常见的图像...

    FTP传输文件的源码 基于服务器

    3. 解析和响应命令:循环读取控制通道的输入,解析为FTP命令,根据命令执行相应操作,如验证用户身份、改变工作目录等。 4. 数据通道管理:根据FTP命令(如RETR或STOR)创建和管理数据通道,进行文件的读写。 5. ...

    深潜数据海洋:Java文件读写全面解析与实战指南

    在Java中,文件读写是通过流来实现的,流是一种从源头到目的地的数据传输通道。Java支持两种基本类型的流:**字节流**和**字符流**。 - **字节流**:适用于任何类型的数据,如图片、音频、视频等二进制文件。主要的...

    tcp文件传输服务器

    总的来说,TCP文件传输服务器涉及了网络编程、并发处理、文件操作等多个方面的知识,是学习和实践网络通信技术的一个很好的应用场景。通过分析和实现这样的系统,开发者可以深入理解TCP/IP协议栈的工作原理,并提高...

    socket文件传输部分代码(java)

    在深入探讨如何利用Java进行socket文件传输之前,我们首先需要理解几个关键概念:socket编程、非阻塞IO、选择器(Selector)、以及文件读写操作。本文将详细解释这些概念,并通过分析提供的部分Java代码片段,阐述...

    基于Socket API 文件传输

    在C/S架构中,服务器负责监听客户端的连接请求,一旦有请求到来,就会建立一个新的连接并处理数据传输。客户端则通过发起连接请求,与服务器建立通信通道,用于发送文件或接收文件。 3. **多线程技术**: 为了...

    java实现网络文件传输

    设计模式中的接口则可以用来规范不同组件之间的交互,例如定义一个`FileTransfer`接口,规定文件传输的相关操作,如`sendFile()`和`receiveFile()`,这样可以使代码更具扩展性和可维护性。 5. **源码解析**: ...

    FAT文件系统 SD卡实验程序代码(读写SD卡

    它的主要功能是管理存储设备上的数据,包括文件的创建、读取、修改和删除等操作。FAT文件系统有多种版本,如FAT12、FAT16、FAT32,以及后来的VFAT,后者主要是为了解决FAT32对长文件名的支持问题。 在这个"SD卡实验...

    解析Linux特殊文件

    在Linux操作系统中,文件系统包含了各种类型的文件,其中包括普通文件、目录文件以及一系列特殊文件,如设备文件(块设备和字符设备)、管道文件、符号链接(软链接)和硬链接等。这些特殊文件在Linux中扮演着至关...

    top_block.zip_FTP文件传输服务器_ftp

    总结来说,“top_block.zip”中的FTP文件传输服务器端实现是基于Python的,它能够提供基本的FTP服务,包括连接管理、身份验证、文件操作等,确保了文件在客户端和服务器之间的安全传输。通过分析和理解“top_block....

    数据传输稳定性的优化

    总的来说,NIO数据传输稳定性优化是一项复杂的工作,涉及到多个层面的考虑和调整。通过不断迭代和优化,我们可以逐步提升系统的可靠性和用户体验。对于开发者来说,理解和掌握这些优化技巧是提升服务质量的关键。

    java的基于Socket的文件传输服务

    3. **数据传输的完整性与可靠性**:TCP协议通过序列号、确认应答、重传机制等确保了数据的完整性和可靠性。在Java中,通过Socket的输入/输出流(InputStream和OutputStream的子类,如DataInputStream和...

    Linux IO数据通道我理解之分享

    ### Linux IO数据通道详解 #### 一、IO数据通道处理层次 在Linux系统中,输入/输出(Input/Output,简称IO)操作是一项基础而...这些机制不仅保证了系统的稳定性和可靠性,也为应用程序提供了高效的数据传输能力。

    ZYNQ 7020实现emmc读写驱动(SDK驱动).zip

    驱动需要设置DMA通道,处理数据传输的开始和结束,并在中断服务程序中处理错误。 4. **错误处理**:在驱动开发过程中,需要考虑到各种可能出现的错误情况,如命令超时、数据校验失败等,并提供相应的恢复机制。 5....

    FTP.rar_FTP传输文件 c++_ftp_ftp vc_ftp 文件传输_vc ftp

    9. **FTP源码分析**:压缩包中的"FTP"文件可能是FTP程序的源代码,分析这个源码可以帮助我们深入理解FTP文件传输的具体实现,包括如何建立连接、发送命令、处理响应以及进行文件读写等操作。 总的来说,这个压缩包...

    java nio 包读取超大数据文件

    - **Buffers**:用来存储数据的对象,是数据传输的载体。 - **Selectors**:多路复用器,用于监控多个Channel的状态变化,支持高效地处理大量并发连接。 - **FileChannel**:用于与文件进行交互的Channel,提供了...

    HDFS读写机制.docx

    - **传输数据:**DataNode接收到请求后,将文件数据传输回客户端。 - **本地处理文件:**客户端接收到数据后,在本地对文件进行相应的处理操作。 #### 二、基础API案例 **1、基础演示接口** 在HDFS中,为了简化...

    C# 进程间通信 命名通道

    4. **数据传输**:客户端和服务器通过各自创建的流对象进行数据读写操作。可以使用`StreamReader`和`StreamWriter`进行文本数据交换,或者直接操作`Stream`进行二进制数据交换。 5. **关闭连接**:通信完成后,应...

    文件传输系统 vc ftp server client

    4. **数据传输**:FTP使用两种通道,控制通道和数据通道。控制通道处理命令交互,数据通道则负责实际的文件传输。 5. **断开连接**:完成操作后,客户端会发送QUIT命令,关闭控制通道,然后断开连接。 【FTP协议的...

Global site tag (gtag.js) - Google Analytics