Java Socket实战之七 使用Socket通信传输文件

Java Socket实战之七 使用Socket通信传输文件

前面几篇文章介绍了使用Java的Socket编程和NIO包在Socket中的应用,这篇文章说说怎样利用Socket编程来实现简单的文件传输。

这里由于前面一片文章介绍了NIO在Socket中的应用,所以这里在读写文件的时候也继续使用NIO包,所以代码看起来会比直接使用流的方式稍微复杂一点点。

下面的示例演示了客户端向服务器端发送一个文件,服务器作为响应给客户端会发一个文件。这里准备两个文件E:/test/server_send.log和E:/test/client.send.log文件,在测试完毕后在客户端和服务器相同目录下会多出两个文件E:/test/server_receive.log和E:/test/client.receive.log文件。

下面首先来看看Server类,主要关注其中的sendFile和receiveFile方法。

  1. packagecom.googlecode.garbagecan.test.socket.nio;
  2. importjava.io.File;
  3. importjava.io.FileInputStream;
  4. importjava.io.FileOutputStream;
  5. importjava.io.IOException;
  6. importjava.net.InetSocketAddress;
  7. importjava.nio.ByteBuffer;
  8. importjava.nio.channels.ClosedChannelException;
  9. importjava.nio.channels.FileChannel;
  10. importjava.nio.channels.SelectionKey;
  11. importjava.nio.channels.Selector;
  12. importjava.nio.channels.ServerSocketChannel;
  13. importjava.nio.channels.SocketChannel;
  14. importjava.util.Iterator;
  15. importjava.util.logging.Level;
  16. importjava.util.logging.Logger;
  17. publicclassMyServer4{
  18. privatefinalstaticLoggerlogger=Logger.getLogger(MyServer4.class.getName());
  19. publicstaticvoidmain(String[]args){
  20. Selectorselector=null;
  21. ServerSocketChannelserverSocketChannel=null;
  22. try{
  23. //Selectorforincomingtimerequests
  24. selector=Selector.open();
  25. //Createanewserversocketandsettononblockingmode
  26. serverSocketChannel=ServerSocketChannel.open();
  27. serverSocketChannel.configureBlocking(false);
  28. //Bindtheserversockettothelocalhostandport
  29. serverSocketChannel.socket().setReuseAddress(true);
  30. serverSocketChannel.socket().bind(newInetSocketAddress(10000));
  31. //Registeracceptsontheserversocketwiththeselector.This
  32. //steptellstheselectorthatthesocketwantstobeputonthe
  33. //readylistwhenacceptoperationsoccur,soallowingmultiplexed
  34. //non-blockingI/Ototakeplace.
  35. serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
  36. //Here'swhereeverythinghappens.Theselectmethodwill
  37. //returnwhenanyoperationsregisteredabovehaveoccurred,the
  38. //threadhasbeeninterrupted,etc.
  39. while(selector.select()>0){
  40. //SomeoneisreadyforI/O,getthereadykeys
  41. Iterator<SelectionKey>it=selector.selectedKeys().iterator();
  42. //Walkthroughthereadykeyscollectionandprocessdaterequests.
  43. while(it.hasNext()){
  44. SelectionKeyreadyKey=it.next();
  45. it.remove();
  46. //Thekeyindexesintotheselectorsoyou
  47. //canretrievethesocketthat'sreadyforI/O
  48. doit((ServerSocketChannel)readyKey.channel());
  49. }
  50. }
  51. }catch(ClosedChannelExceptionex){
  52. logger.log(Level.SEVERE,null,ex);
  53. }catch(IOExceptionex){
  54. logger.log(Level.SEVERE,null,ex);
  55. }finally{
  56. try{
  57. selector.close();
  58. }catch(Exceptionex){}
  59. try{
  60. serverSocketChannel.close();
  61. }catch(Exceptionex){}
  62. }
  63. }
  64. privatestaticvoiddoit(finalServerSocketChannelserverSocketChannel)throwsIOException{
  65. SocketChannelsocketChannel=null;
  66. try{
  67. socketChannel=serverSocketChannel.accept();
  68. receiveFile(socketChannel,newFile("E:/test/server_receive.log"));
  69. sendFile(socketChannel,newFile("E:/test/server_send.log"));
  70. }finally{
  71. try{
  72. socketChannel.close();
  73. }catch(Exceptionex){}
  74. }
  75. }
  76. privatestaticvoidreceiveFile(SocketChannelsocketChannel,Filefile)throwsIOException{
  77. FileOutputStreamfos=null;
  78. FileChannelchannel=null;
  79. try{
  80. fos=newFileOutputStream(file);
  81. channel=fos.getChannel();
  82. ByteBufferbuffer=ByteBuffer.allocateDirect(1024);
  83. intsize=0;
  84. while((size=socketChannel.read(buffer))!=-1){
  85. buffer.flip();
  86. if(size>0){
  87. buffer.limit(size);
  88. channel.write(buffer);
  89. buffer.clear();
  90. }
  91. }
  92. }finally{
  93. try{
  94. channel.close();
  95. }catch(Exceptionex){}
  96. try{
  97. fos.close();
  98. }catch(Exceptionex){}
  99. }
  100. }
  101. privatestaticvoidsendFile(SocketChannelsocketChannel,Filefile)throwsIOException{
  102. FileInputStreamfis=null;
  103. FileChannelchannel=null;
  104. try{
  105. fis=newFileInputStream(file);
  106. channel=fis.getChannel();
  107. ByteBufferbuffer=ByteBuffer.allocateDirect(1024);
  108. intsize=0;
  109. while((size=channel.read(buffer))!=-1){
  110. buffer.rewind();
  111. buffer.limit(size);
  112. socketChannel.write(buffer);
  113. buffer.clear();
  114. }
  115. socketChannel.socket().shutdownOutput();
  116. }finally{
  117. try{
  118. channel.close();
  119. }catch(Exceptionex){}
  120. try{
  121. fis.close();
  122. }catch(Exceptionex){}
  123. }
  124. }
  125. }

下面是Client程序代码,也主要关注sendFile和receiveFile方法
  1. packagecom.googlecode.garbagecan.test.socket.nio;
  2. importjava.io.File;
  3. importjava.io.FileInputStream;
  4. importjava.io.FileOutputStream;
  5. importjava.io.IOException;
  6. importjava.net.InetSocketAddress;
  7. importjava.net.SocketAddress;
  8. importjava.nio.ByteBuffer;
  9. importjava.nio.channels.FileChannel;
  10. importjava.nio.channels.SocketChannel;
  11. importjava.util.logging.Level;
  12. importjava.util.logging.Logger;
  13. publicclassMyClient4{
  14. privatefinalstaticLoggerlogger=Logger.getLogger(MyClient4.class.getName());
  15. publicstaticvoidmain(String[]args)throwsException{
  16. newThread(newMyRunnable()).start();
  17. }
  18. privatestaticfinalclassMyRunnableimplementsRunnable{
  19. publicvoidrun(){
  20. SocketChannelsocketChannel=null;
  21. try{
  22. socketChannel=SocketChannel.open();
  23. SocketAddresssocketAddress=newInetSocketAddress("localhost",10000);
  24. socketChannel.connect(socketAddress);
  25. sendFile(socketChannel,newFile("E:/test/client_send.log"));
  26. receiveFile(socketChannel,newFile("E:/test/client_receive.log"));
  27. }catch(Exceptionex){
  28. logger.log(Level.SEVERE,null,ex);
  29. }finally{
  30. try{
  31. socketChannel.close();
  32. }catch(Exceptionex){}
  33. }
  34. }
  35. privatevoidsendFile(SocketChannelsocketChannel,Filefile)throwsIOException{
  36. FileInputStreamfis=null;
  37. FileChannelchannel=null;
  38. try{
  39. fis=newFileInputStream(file);
  40. channel=fis.getChannel();
  41. ByteBufferbuffer=ByteBuffer.allocateDirect(1024);
  42. intsize=0;
  43. while((size=channel.read(buffer))!=-1){
  44. buffer.rewind();
  45. buffer.limit(size);
  46. socketChannel.write(buffer);
  47. buffer.clear();
  48. }
  49. socketChannel.socket().shutdownOutput();
  50. }finally{
  51. try{
  52. channel.close();
  53. }catch(Exceptionex){}
  54. try{
  55. fis.close();
  56. }catch(Exceptionex){}
  57. }
  58. }
  59. privatevoidreceiveFile(SocketChannelsocketChannel,Filefile)throwsIOException{
  60. FileOutputStreamfos=null;
  61. FileChannelchannel=null;
  62. try{
  63. fos=newFileOutputStream(file);
  64. channel=fos.getChannel();
  65. ByteBufferbuffer=ByteBuffer.allocateDirect(1024);
  66. intsize=0;
  67. while((size=socketChannel.read(buffer))!=-1){
  68. buffer.flip();
  69. if(size>0){
  70. buffer.limit(size);
  71. channel.write(buffer);
  72. buffer.clear();
  73. }
  74. }
  75. }finally{
  76. try{
  77. channel.close();
  78. }catch(Exceptionex){}
  79. try{
  80. fos.close();
  81. }catch(Exceptionex){}
  82. }
  83. }
  84. }
  85. }

首先运行MyServer4类启动监听,然后运行MyClient4类来向服务器发送文件以及接受服务器响应文件。运行完后,分别检查服务器和客户端接收到的文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值