2015-01-23 7 views
0

Я полный noob на Java, поэтому извиняюсь, если это ошибка новобранец. Я пробовал Java NIO, я до сих пор не вышел на сцену, где я использую неблокирующую функцию. Я просто не могу заставить сервер читать строку, я понимаю, что нелегко послать Bytebuffer с одной стороны и попытаться интерпретировать его как String на другой стороне, но я все еще не могу понять, куда иду неправильно. Вот кодВходной поток readUTF не может читать UTF

***************************** SERVER SIDE *********** ***************************

class MyBlockingServer extends Thread 
{ 
    private int M_PortNumber; 
    private ServerSocket M_ServerSocket; 

    MyBlockingServer(int PortNumber) 
    { 
     M_PortNumber = PortNumber; 
     try { 
      M_ServerSocket = new ServerSocket(M_PortNumber); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    public void run() 
    { 
     int my_number = 0; 
     while(true) 
     { 
      try { 
       Socket Server = M_ServerSocket.accept(); 


       DataInputStream inputStream = new DataInputStream(Server.getInputStream()); 
       System.out.println("[SERVER]" +inputStream.readUTF()); 


       DataOutputStream outputStream = new DataOutputStream(Server.getOutputStream()); 
       outputStream.writeUTF("Thanks for connection, you suck tata" + " "+ my_number); 

       my_number++; 
       Server.close(); 

      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    void socket_close() 
    { 
     try { 
      M_ServerSocket.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

} 

public class JavaBlocking 
{ 

    public static void main(String []args) 
    { 
     MyBlockingServer Server = new MyBlockingServer(8000); 
     try { 
      Server.start(); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 
} 

**************** ***************СТОРОНА КЛИЕНТА*********************************

public class JavaChannels 
{ 

    public static void main(String []args) 
    { 
     SocketChannel client_channel = null; 

     try { 
      client_channel = SocketChannel.open(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println("[Client] Socket channel open"); 

     try { 
      client_channel.connect(new InetSocketAddress("127.0.0.1",8000)); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println("[Client] Socket channel connected"); 

     ByteBuffer my_buffer = ByteBuffer.allocate(48); 
     my_buffer.clear(); 

     try { 
      my_buffer.put("WHY_YOU_NO_WORK".getBytes("UTF-8")); 
     } catch (UnsupportedEncodingException e2) { 
      // TODO Auto-generated catch block 
      e2.printStackTrace(); 
     } 

     my_buffer.flip(); 

     try { 
      int bytes_written = client_channel.write(my_buffer); 

      while(my_buffer.hasRemaining()) 
      { 
       bytes_written = client_channel.write(my_buffer); 
      } 

      System.out.println("[Client] Wrote "+ bytes_written +" bytes"); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println("[Client] Socket channel write finished"); 

     my_buffer.clear(); 
     my_buffer.flip(); 


     try { 
      client_channel.read(my_buffer); 
     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 

     System.out.println("[Client] server says" + new String(my_buffer.array())); 

     try { 
      client_channel.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 


} 

ошибка я получаю это

java.io.EOFException в java.io.DataI nputStream.readFully (DataInputStream.java:197) при java.io.DataInputStream.readUTF (DataInputStream.java:609) при java.io.DataInputStream.readUTF (DataInputStream.java:564) при netty_tutorial.blocking.MyBlockingServer. run (JavaBlocking.java:39)

Это как-то указывает мне, что readUTF не читает формат UTF, а что-то еще.

В общем, что я делаю это

Сервер -> ReadUTF

Client -> String -> Байт массив в UTF-8 -> ByteBuffer -> Написать

Поскольку я явно кодирую массив байтов в UTF-8. почему не может прочитать NOTF?

+0

Если вы используете readUTF, другая сторона должна использовать writeUTF. Если вы не изучите этот особый формат и не следуете маленькому шрифту: длина двух байтов, затем символы и т. Д. И т. Д., Но на самом деле не конвертированы в UTF-8 (хотя это может не вызвать никаких проблем, если ваши символы Юникода не очень дикие.) – laune

+0

У ByteBuffer нет метода writeUTF, никаких обходных решений? –

+0

DataOutputStream имеет. – laune

ответ

3

Метод DataInput.readUTFне чтения строки UTF-8 кодируются, она считывает данные в конкретном формате, который создает DataOutput.writeUTF, который подобен, но не такой же, как истинный UTF-8:

  • начинается с 16-битного беззнакового целого числа, указывающего число следующих байтов, которые составляют строку
  • следующие следующие байты являются модифицированной формой UTF-8, где U + 0000 представляется в двух байтах, а не в 1 (так что двоичное представление строки не может содержать 0 байтов), а дополнительные символы выше U + FFFF представлены как s суррогатная пара, причем высокий и низкий суррогат кодируется в UTF-8 отдельно по 3 байта каждый (истинный UTF-8 будет кодировать всю дополнительную кодовую точку за один раз, используя в общей сложности четыре байта).

Если вы пишете истинный UTF-8, то вам необходимо прочитать настоящую UTF-8, если вы хотите readUTF то вы должны writeUTF.

Если вы хотите writeUTF к ByteBuffer это довольно просто реализовать OutputStream оболочку вокруг буфера, который вы можете в свою очередь, завернуть в DataOutputStream:

class ByteBufferBackedOutputStream extends OutputStream{ 
    ByteBuffer buf; 
    ByteBufferBackedOutputStream(ByteBuffer buf){ 
    this.buf = buf; 
    } 
    public synchronized void write(int b) throws IOException { 
    buf.put((byte) b); 
    } 

    public synchronized void write(byte[] bytes, int off, int len) throws IOException { 
    buf.put(bytes, off, len); 
    } 

} 

(source)

+0

Спасибо, ваше объяснение пришло мне в голову. Как-то название функции не указывало на это :). –

+0

Это не тот случай, когда вы должны использовать 'DataOutputStream.writeUTF', есть несколько вариантов, которые вы можете решить, я включил простейший в своем ответе. –

+0

@PeterLawrey, если вы не используете никаких дополнительных символов, да. –

1

Вам необходимо написать формат, который ожидает DataInputStream.

например.

public static void writeUTF(ByteBuffer bb, String text) { 
    byte[] bytes = text.getBytes("UTF-8"); 
    if (bytes.length > 1 << 16) 
     throw new IllegalArgumentException(); 
    bb.putShort((short) bytes.length); 
    bb.write(bytes); 
} 

Примечание: в то время как writeUTF будет написать \0 как два байта вместо одного, то readUTF примет это как 1 или 2 байта.