【问题标题】:how to sent byte[ ] array in socket如何在套接字中发送字节[]数组
【发布时间】:2017-05-08 15:59:30
【问题描述】:

我是 Java 新手,我试图通过套接字发送一个字节 [] 数组,但它本身将我的数组转换为字符串然后发送它。到目前为止还可以,但问题是我需要接收数组类型的消息,或者我必须将字符串转换为数组,以使解密方法能够解密数组(解密方法的输入必须是字节数组)。我该怎么做?

我的服务器端相关代码是:

private void IssuingTickets() throws Exception{

        String socketUsername = reader.readLine();//rcv username
        String socketPassword = reader.readLine();//rcv password
        writer.println("Lemme Check!");  


        Properties prop = new Properties();
        prop.load(new FileInputStream("input"));
        String fileUsername = prop.getProperty("username");
        String filePassword = null;
        if (prop.getProperty("password") != null) {
            filePassword = prop.getProperty("password");}
        if (socketPassword.equals(filePassword)){ 
            String sessionKeyBobKdc = new Scanner(new File("sBOBandKDC")).useDelimiter("\\Z").next();
            byte[] ClientTicket = encrypt(sessionKeyBobKdc, filePassword);
            System.out.println("clietn ticket =   " + ClientTicket+"   ArraytoString   " + Arrays.toString(ClientTicket));
            writer.println(ClientTicket);
            String KDCkey = new Scanner(new File("KDCkey")).useDelimiter("\\Z").next();
            String UnEncTGT= sessionKeyBobKdc.concat(socketUsername);
            byte[] TGT = encrypt(UnEncTGT, KDCkey);
            writer.println(TGT);

            }else
                {writer.println("Please try again later!");}

            }    


    public static byte[] encrypt(String plainText1, String encryptionKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
        return cipher.doFinal(plainText1.getBytes("UTF-8"));
            }



    public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
        cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
        return new String(cipher.doFinal(cipherText),"UTF-8");
            }
}

Clientside相关代码为:

        private void recieveTickts() throws IOException, InterruptedException, Exception{
                String msg = reader.readLine(); //Lemme  check
                System.out.println("Server :" + msg); 
                TimeUnit.SECONDS.sleep(3);
                String  Sth = reader.readLine(); //please try again
                if(Sth.equals("Please try again later!")){
                    System.out.println(Sth);
                    System.exit(1);
                }else{
                ClientTicket = Sth;
                String TGT = reader.readLine();
                System.out.println("Encrypted key between Client and KDC is  " + ClientTicket + "  and the TGT is " + TGT);
                TimeUnit.SECONDS.sleep(3);
                System.out.println("SUCCESSFUL"); }          
                byte[] b = ClientTicket.getBytes();
                System.out.println("b= " + b);
                String sessionKeyBobKdc = decrypt(b, Password);
                System.out.println(Password + "session key is "+ sessionKeyBobKdc);
        }

感谢先进的家伙..

【问题讨论】:

  • 你为什么不直接改变你的encryptdecrypt 方法来使用字节数组而不是字符串呢?这将是一个更好的主意,IMO。让调用者进行他们需要的任何文本到二进制的转换。
  • 提示:永远不要使用空的 catch 块。隐藏错误消息是您想要做的最后件事。
  • 感谢 Jon 的快速响应,实际上加密和解密方法正在使用字节数组
  • 感谢 GhostCat,我会尽快修复它

标签: java arrays string sockets


【解决方案1】:

我记录了代码来帮助你,但这基本上是一种快速而肮脏的方式,永远不会停止监听数据,然后还将接收到的返回为byte[]如果您不需要一直收听,只需修改此代码以在收到消息后停止收听

您可以使用参数来定义消息完成的标志等,从而使其更具动态性。

我使用 StringBuilder 作为一个小缓冲区。并定义一旦我收到一个 LF,一条消息就完成了。其他所有内容都放入“缓冲区”中。此外,我过滤掉了 CR,因为我不希望它们出现在我的消息中。

Socket client;
StringBuilder sb = new StringBuilder();
String result = "";
int c;
try
{
  InputStream inputStream = client.getInputStream();
  while ( ( c = inputStream.read() ) >= 0 ) // Loop to listen for data until the connection is dead
  {
    if ( c == 0x0a ) // 0x0a is the hex for a LineFeed ( LF )
    {
      result = sb.toString(); // put everything you received so far as a final message
      sb.delete( 0, sb.length() ); // clear your message "buffer"
    }
    else if ( c != 0x0d /* <CR> */ ) // Not necessary but it helps keeping the message clear
    {
      sb.append( (char) c ); // add the received integer as char to the message "buffer"
    }
    if ( !result.isEmpty() ) // Catch that a message is received
    {
      log.fine( "received message: " + result ); // just log for tracing
      return result.getBytes(StandardCharsets.UTF_8); // return the byte[] of the message with the needed Charset.         
    }
  }
}
catch ( Exception e )
{
  log.warning( e.getMessage() );
}

【讨论】:

  • 没问题。作为注释。我忘了提到client.getInputStream() 来自我声明为客户的Socket。希望cmets对大家有所了解。
  • 这对BufferedReader.readLine()没有任何改进,因为密文可以随时包含LF和CR,而且StringStringBuffer都不是二进制数据的容器,尝试使用线路 I/O 的整个方案注定要失败。
  • @EJP 是的,但我知道他现在想实现 Socket 功能,这就是我在一个非常适合我的自定义需求中做到的。我说他应该根据自己的需要修改它。如果他不打算使用 Socket 和 tcp,我的整个答案将被弃用。
猜你喜欢
  • 2010-11-13
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多