chenshi1781 2009-11-30 08:35
浏览 187
已采纳

500块钱一个问题

在做j2se中用socket传输文件速度很慢,大概30k/s,如果谁能解决这个速度问题,提高到100k/s左右,将给予500块的酬劳。
[b]问题补充:[/b]
联系QQ(116870791)

  • 写回答

1条回答 默认 最新

  • wanghaolovezlq 2009-11-30 08:46
    关注

    用nio异步I/O来实现socket传输就快多了

    [code="java"]
    package nio.file;

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.util.Iterator;

    /**

    • 测试文件下载的NIOServer
    • @author tenyears.cn
      */
      public class NIOServer {
      static int BLOCK = 4096;
      static String charCoding = "utf-8";
      // 处理与客户端的交互
      public class HandleClient {
      protected FileChannel channel;
      protected ByteBuffer buffer;

      public HandleClient() throws IOException {
          this.channel = new FileInputStream(filename).getChannel();
          this.buffer = ByteBuffer.allocate(BLOCK);
      }
      
      public ByteBuffer readBlock() {
          try {
              buffer.clear();
              int count = channel.read(buffer);
              buffer.flip();
              if (count <= 0)
                  return null;
          } catch (IOException e) {
              e.printStackTrace();
          }
          return buffer;
      }
      
      public void close() {
          try {
              channel.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      

      }

      protected Selector selector;
      protected String filename = "c:\file.war"; // a big file
      protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);
      protected CharsetDecoder decoder;

      public NIOServer(int port) throws IOException {
      selector = this.getSelector(port);
      Charset charset = Charset.forName(charCoding);
      decoder = charset.newDecoder();
      }

      // 获取Selector
      protected Selector getSelector(int port) throws IOException {
      ServerSocketChannel server = ServerSocketChannel.open();
      Selector sel = Selector.open();
      server.socket().bind(new InetSocketAddress(port));
      server.configureBlocking(false);
      server.register(sel, SelectionKey.OP_ACCEPT);
      return sel;
      }

      // 监听端口
      public void listen() {
      try {
      for (;;) {
      selector.select();
      Iterator iter = selector.selectedKeys()
      .iterator();
      while (iter.hasNext()) {
      SelectionKey key = iter.next();
      iter.remove();
      handleKey(key);
      }
      }
      } catch (IOException e) {
      e.printStackTrace();
      }
      }

      // 处理事件
      protected void handleKey(SelectionKey key) throws IOException {
      if (key.isAcceptable()) { // 接收请求
      ServerSocketChannel server = (ServerSocketChannel) key.channel();
      SocketChannel channel = server.accept();
      channel.configureBlocking(false);
      channel.register(selector, SelectionKey.OP_READ);
      } else if (key.isReadable()) { // 读信息
      SocketChannel channel = (SocketChannel) key.channel();
      int count = channel.read(clientBuffer);
      if (count > 0) {
      clientBuffer.flip();
      CharBuffer charBuffer = decoder.decode(clientBuffer);
      System.out.println("Client >>" + charBuffer.toString());
      SelectionKey wKey = channel.register(selector,
      SelectionKey.OP_WRITE);
      wKey.attach(new HandleClient());
      } else
      channel.close();
      clientBuffer.clear();
      } else if (key.isWritable()) { // 写事件
      SocketChannel channel = (SocketChannel) key.channel();
      HandleClient handle = (HandleClient) key.attachment();
      ByteBuffer block = handle.readBlock();
      if (block != null)
      channel.write(block);
      else {
      handle.close();
      channel.close();
      }
      }
      }

      public static void main(String[] args) {
      int port = 12345;
      try {
      NIOServer server = new NIOServer(port);
      System.out.println("Listernint on " + port);
      while (true) {
      server.listen();
      }
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      }

    [/code]

    [code="java"]
    package nio.file;

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetEncoder;
    import java.util.Iterator;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    /**

    • 文件下载客户端
    • @author tenyears.cn
      */
      public class NIOClient {
      static int SIZE = 100;
      static InetSocketAddress ip = new InetSocketAddress("localhost", 12345);

      // CharsetDecorder并不是线程安全的,在高并发的状态下会出问题。
      static CharsetEncoder encoder = Charset.forName("utf-8").newEncoder();

      static class Download implements Runnable {
      protected int index;

      public Download(int index) {
          this.index = index;
      }
      
      public void run() {
          try {
              long start = System.currentTimeMillis();
              SocketChannel client = SocketChannel.open();
              client.configureBlocking(false);
              Selector selector = Selector.open();
              client.register(selector, SelectionKey.OP_CONNECT);
              client.connect(ip);
              ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
              int total = 0;
              FOR: for (;;) {
                  selector.select();
                  Iterator<SelectionKey> iter = selector.selectedKeys()
                          .iterator();
                  while (iter.hasNext()) {
                      SelectionKey key = iter.next();
                      iter.remove();
                      if (key.isConnectable()) {
                          SocketChannel channel = (SocketChannel) key
                                  .channel();
                          if (channel.isConnectionPending())
                              channel.finishConnect();
                          channel.write(encoder.encode(CharBuffer
                                  .wrap("Hello from " + index)));
                          channel.register(selector, SelectionKey.OP_READ);
                      } else if (key.isReadable()) {
                          SocketChannel channel = (SocketChannel) key
                                  .channel();
                          int count = channel.read(buffer);
                          if (count > 0) {
                              total += count;
                              buffer.clear();
                          } else {
                              client.close();
                              break FOR;
                          }
                      }
                  }
              }
              double last = (System.currentTimeMillis() - start) * 1.0 / 1000;
              System.out.println("Thread " + index + " downloaded " + total
                      + "bytes in " + last + "s.");
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      

      }

      public static void main(String[] args) throws IOException {
      ExecutorService exec = Executors.newFixedThreadPool(SIZE);
      for (int index = 0; index < SIZE; index++) {
      exec.execute(new Download(index));
      }
      exec.shutdown();
      }
      }

    [/code]

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题