如何使用套接字通道发送文件名和文件内容

时间:2015-07-09 09:49:37

标签: java sockets network-programming nio serversocket

我想使用socketchannel一起发送文件名和文件内容。 我试图将文件名转换为字节,将这些字节包装在bytebuffer中,然后将这些缓冲区内容发送到客户端(这是在服务器端)。

在客户端,我试图遍历缓冲区中的内容,将字节转换为字符并检查是否存在特殊字符以记录文件名的结尾。当识别出该字符时,我调用缓冲区方法compact(),以便我现在可以开始阅读内容。但这不起作用!我的客户端第一次在循环while(bb.hasRemaining())没有中断,并且没有从这个循环打印字符!!

服务器端

FileChannel sbc;
    ServerSocketChannel ssc=null;
    SocketChannel clientchannel=null;

try { 

 ssc=ServerSocketChannel.open();
 ssc.bind(new InetSocketAddress(5002));

 clientchannel=ssc.accept();

String filename=f.getName()+"?";
  byte[] nameinbytes=filename.getBytes("UTF-8");
System.out.println("name of file to send: "+filename);
ByteBuffer namebuffer=ByteBuffer.wrap(nameinbytes);
clientchannel.write(namebuffer);

                sbc=FileChannel.open(f.toPath());
                 ByteBuffer buff=ByteBuffer.allocate(10000000);

                 int bytesread=sbc.read(buff);
                 double read=(double)bytesread;
                 while(bytesread != -1){
                read+=(double) bytesread;
                buff.flip();
               clientchannel.write(buff);
                buff.clear();
                System.out.println("current position: "+sbc.position());
                bytesread=sbc.read(buff);
                 }
  System.out.println("file data written");

客户端

SocketAddress address=new InetSocketAddress(InetAddress.getLocalHost(),5002);
     clientChannel=SocketChannel.open(address);
     ByteBuffer bb=ByteBuffer.allocate(10000000);
     int bytesRead=clientChannel.read(bb);
     String filename="";
     while(bb.hasRemaining()){
         byte bm=bb.get();
         char c=(char)(bm & 0xFF);
         System.out.println(c);
         if(c != '?'){
             filename+=Character.toString(c);
         }else{
             bb.compact();
             break;
         }
     }

      File file=new File("C:\\Users\\C-I-C\\Desktop\\fromclient\\"+filename);

     bout =new FileOutputStream(file);
      sbc=bout.getChannel();

     while(bytesRead != -1){
       bb.flip();
       sbc.write(bb);
       bb.clear();
      bytesRead=clientChannel.read(bb);
     }
     System.out.println("received: "+filename);

如何使用相同的频道发送文件名和文件内容?

1 个答案:

答案 0 :(得分:0)

服务器端

  1. 将文件名转换为字节数组。
  2. 将字节数组包装在ByteBuffer对象中。
  3. 将ByteBuffer对象内容发送到套接字通道
  4. 发送包含文件名的缓冲区(当然是以字节为单位):

    1. 现在创建另一个ByteBuffer对象并为其指定大小
    2. 开始从FileChannel对象读取文件内容到缓冲区。
    3. 在while循环中,开始将内容发送到套接字通道,直到到达文件通道中的文件末尾。

      ServerSocket server=ServerSocket.open();
      server.bind(new InetSocketAddress(1000));
      SocketChannel clientChannel= server.accept();
      File fileToSend=new File("stalkunderflow.txt").
      String filename=fileToSend.getName();
      byte[] nameBytes=filename.getBytes("UTF-8");
      ByteBuffer nameBuffer=ByteBuffer.wrap(nameBytes);
      clientChannel.write(nameBuffer);
      
      //now  prepare and send file contents
      
      FileChannel sbc=FileChannel.open(fileToSend.toPath());
                   ByteBuffer buff=ByteBuffer.allocate(10000000);
      
                   int bytesread=sbc.read(buff);
      
                   while(bytesread != -1){
                  buff.flip();
                 clientChannel.write(buff);
                  buff.compact();
                  bytesread=sbc.read(buff);
                   }
      
    4. 客户端

      1. 创建一个ByteBuffer对象(可以称之为nameBuffer)并给它一个大小(不大)。

      2. 将套接字通道中的内容写入缓冲区。

      3. 翻转缓冲区并开始将缓冲区内容写入字节数组。(在while循环中执行)

      4. 将字节数组转换为字符串,并且您有文件名。

      5. 之后,创建另一个ByteBuffer对象(称之为nameBuffer)以存储文件内容,现在您将从此nameBuffer读取到文件通道,该文件通道使用从nameBuffer获取的名称写入文件。

         //this is a test enviroment,therefore my server is running on the same machine as the client. 
        SocketAddress address=new InetSocketAddress(InetAddress.getLocalHost(),1000);
         SocketChannel clientChannel=SocketChannel.open(address);
        
         ByteBuffer namebuff=ByteBuffer.allocate(500);
         clientChannel.read(namebuff);
        
        byte[] namebyte=new byte[500];
        String filename="";
        
        int position=namebuff.position();
        
         while(namebuff.hasRemaining()){
            namebyte[position]=namebuff.get();
            position=namebuff.position();
         }
         filename=new String(namebyte,0,position);
        
         File file=new File(filename);
        
         ByteBuffer bb=ByteBuffer.allocate(10000000);
         int bytesRead=clientChannel.read(bb);
         FileOutputStream bout =new FileOutputStream(file);
          FileChannel sbc=bout.getChannel();
        
         while(bytesRead != -1){
           bb.flip();
           sbc.write(bb);
           bb.compact();
          bytesRead=clientChannel.read(bb);
         }