通过JavaSSL套接字写入时,第一个字节将丢失

通过JavaSSL套接字写入时,第一个字节将丢失,java,sockets,ssl,byte,Java,Sockets,Ssl,Byte,我以字节数组格式发送多个命令,并根据在典型的客户机/服务器通信中发送的命令接收响应。我的Java应用程序是在Windows 7上运行的客户端,我知道要发送什么命令,以及在响应中希望接收什么。但是,我对服务器源代码没有任何控制或了解 我遇到的问题是,在我发送的第二个命令或之后的任何命令中,数组的第一个字节被删除。当我发送第一个命令时,我得到了正确的响应,因为第一个字节没有被删除。当发送下一个命令或之后的任何命令时,会删除服务器不响应的第一个字节,因为该命令的格式不适合服务器识别 我通过Java S

我以字节数组格式发送多个命令,并根据在典型的客户机/服务器通信中发送的命令接收响应。我的Java应用程序是在Windows 7上运行的客户端,我知道要发送什么命令,以及在响应中希望接收什么。但是,我对服务器源代码没有任何控制或了解

我遇到的问题是,在我发送的第二个命令或之后的任何命令中,数组的第一个字节被删除。当我发送第一个命令时,我得到了正确的响应,因为第一个字节没有被删除。当发送下一个命令或之后的任何命令时,会删除服务器不响应的第一个字节,因为该命令的格式不适合服务器识别

我通过Java SSLSocket DataOutputStream发送这些命令,当然我在DataInputStream上接收响应。我首先与服务器进行握手,并在握手成功后继续。此时,当我发送第一个命令并接收到以十六进制表示的响应时:

Sending: 01 03 03 
Receive: 01 0e fd 85 02 09 01 01 04 01 06
正在发送的下一个命令:

Sending: 01 48 65 6c 6c 6f
但这就是我没有收到服务器响应的地方

在打印javax.net.debug输出时,我可以看到第一个字节“01”确实丢失了

Padded plaintext before ENCRYPTION:  len = 32
0000: 48 65 6C 6C 6F FE 57 F9   4A 29 13 8F 2B AB 71 A3  Hello.W.J)..+.q.
0010: 16 12 29 FF D5 DE 12 48   8B 06 06 06 06 06 06 06  ..)....H........
main, WRITE: TLSv1 Application Data, length = 32
[Raw write]: length = 37
0000: 17 03 01 00 20 34 42 ED   88 FC 41 2D 13 1A FD BA  .... 4B...A-....
0010: 64 0E 9D C7 FE 11 76 96   48 09 A6 BC B2 BC 0E FA  d.....v.H.......
0020: C8 5B 79 4B 82                                     .[yK.
以下是我的源代码:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.TrustManager;
import java.security.KeyStore;

public class SSLSocketTest 
{
    private SSLSocket sslSocket = null;
    private SSLSocketFactory sslSocketFactory = null;
    private String ipAddress = "192.168.100.99";
    private int port = 9999;

    DataOutputStream dataOS = null;
    DataInputStream dataIS = null;

    private boolean handshakeSuccessful = false;

    public static void main(String[] args) 
    {
        SSLSocketTest sslSocketTest = new SSLSocketTest();
        sslSocketTest.sslSocketConnect();
    }

    SSLSocketTest()
    {
        System.setProperty("javax.net.debug", "all");

        try{
            File certFile = new File("cacerts");

            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            char[] certPassword = "changeit".toCharArray();
            InputStream fileIS = new FileInputStream(certFile);
            keyStore.load(fileIS, certPassword);
            fileIS.close();

            SSLContext sslContext = SSLContext.getInstance("TLSv1");

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            X509TrustManager defaultTrustManager = (X509TrustManager)trustManagerFactory.getTrustManagers()[0];

            sslContext.init(null, new TrustManager[] {defaultTrustManager}, null);
            sslSocketFactory = sslContext.getSocketFactory();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void sslSocketConnect()
    {
        try{
            sslSocket = (SSLSocket) sslSocketFactory.createSocket(ipAddress, port);

            dataOS = new DataOutputStream(sslSocket.getOutputStream());
            dataIS = new DataInputStream(sslSocket.getInputStream());

            sslSocket.setSoTimeout(15000);

            //Handshake
            sslSocket.addHandshakeCompletedListener(new MyHandshakeListener());
            sslSocket.startHandshake();
            while(!handshakeSuccessful)
            {
                Thread.sleep(100);
            }

            //Sending commands
            byte[] firstCommand = new byte[]{(byte)0x01, (byte)0x03, (byte)0x03};

            String[] firstCommandResponse = processCommand(firstCommand);

            byte[] secondCommand = new byte[]{(byte)0x01, (byte)0x48, (byte)0x65, (byte)0x6C, (byte)0x6C, (byte)0x6F};

            String[] secondCommandResponse = processCommand(secondCommand);

            disconnect();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void disconnect()
    {
        try{
            byte[] endConnection = new byte[]{(byte)0x01, (byte)0x01, (byte)0x02, (byte)0x03};

            processCommand(endConnection);

            dataOS.close();
            dataIS.close();
            sslSocket.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public String[] processCommand(byte[] command)
    {
        String[] returnResponse = null;

        byte[] commandResponse = new byte[120];
        byte[] trimCommandResponse;

        try{
            int commandResponseLength = -1;
            int errorCount = 0;

            while(commandResponseLength == -1)
            {   
                StringBuilder cmdStr = new StringBuilder();
                cmdStr.append("Sending: ");
                for(int i=0; i<command.length; i++)
                {
                    cmdStr.append(fixHexStringData(Integer.toHexString(command[i])) + " ");
                }
                System.out.println(cmdStr.toString());

                dataOS.write(command, 0, command.length);
                dataOS.flush();

                commandResponseLength = dataIS.read(commandResponse);

                errorCount++;
                if(errorCount == 3)
                {
                    throw new Exception();
                }
            }

            returnResponse = new String[commandResponseLength];
            trimCommandResponse = new byte[commandResponseLength];

            //Getting Reponse Data
            for(int i=0; i<commandResponseLength; i++)
            {
                returnResponse[i] = fixHexStringData(Integer.toHexString(commandResponse[i]));
                trimCommandResponse[i] = commandResponse[i];
            }

            StringBuilder rcvStr = new StringBuilder();             
            rcvStr.append("Receive: ");
            for(int i=0; i<returnResponse.length; i++)
            {
                rcvStr.append(returnResponse[i] + " ");
            }
            System.out.println(rcvStr.toString());

        }catch(Exception e){
            e.printStackTrace();
        }

        return returnResponse;
    }

    private String fixHexStringData(String dataByte)
    {
        if(dataByte.length() < 2)
        {       
            dataByte = "0" + dataByte;
        }
        else if(dataByte.length() > 2)
        {
            dataByte = dataByte.substring(dataByte.length()-2);
        }
        return dataByte;
    }

    class MyHandshakeListener implements HandshakeCompletedListener 
    {
          public void handshakeCompleted(HandshakeCompletedEvent e)
          {
            System.out.println("Handshake succesful!");

            handshakeSuccessful = true;
          }
    }
}
import java.io.DataInputStream;
导入java.io.DataOutputStream;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.InputStream;
导入javax.net.ssl.SSLSocketFactory;
导入javax.net.ssl.TrustManagerFactory;
导入javax.net.ssl.HandshakeCompletedEvent;
导入javax.net.ssl.HandshakeCompletedListener;
导入javax.net.ssl.SSLContext;
导入javax.net.ssl.SSLSocket;
导入javax.net.ssl.X509TrustManager;
导入javax.net.ssl.TrustManager;
导入java.security.KeyStore;
公共类SSLSocketTest
{
私有SSLSocket SSLSocket=null;
私有SSLSocketFactory SSLSocketFactory=null;
专用字符串ipAddress=“192.168.100.99”;
专用int端口=9999;
DataOutputStream dataOS=null;
DataInputStream数据为空;
私有布尔握手成功=false;
公共静态void main(字符串[]args)
{
SSLSocketTest SSLSocketTest=新的SSLSocketTest();
sslSocketTest.sslSocketConnect();
}
SSLSocketTest()
{
setProperty(“javax.net.debug”、“all”);
试一试{
文件certFile=新文件(“cacerts”);
KeyStore KeyStore=KeyStore.getInstance(KeyStore.getDefaultType());
char[]certPassword=“changeit”.toCharArray();
InputStream fileIS=新文件InputStream(certFile);
加载(fileIS,certPassword);
fileIS.close();
SSLContext SSLContext=SSLContext.getInstance(“TLSv1”);
TrustManagerFactory TrustManagerFactory=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(密钥库);
X509TrustManager defaultTrustManager=(X509TrustManager)trustManagerFactory.GetTrustManager()[0];
init(null,新信任管理器[]{defaultTrustManager},null);
sslSocketFactory=sslContext.getSocketFactory();
}捕获(例外e){
e、 printStackTrace();
}
}
public void sslSocketConnect()
{
试一试{
sslSocket=(sslSocket)sslSocketFactory.createSocket(IP地址,端口);
dataOS=新的DataOutputStream(sslSocket.getOutputStream());
dataIS=新的DataInputStream(sslSocket.getInputStream());
sslSocket.setSoTimeout(15000);
//握手
addHandshakeCompletedListener(新的MyHandshakeListener());
sslSocket.startHandshake();
而(!握手成功)
{
睡眠(100);
}
//发送命令
字节[]第一个命令=新字节[]{(字节)0x01,(字节)0x03,(字节)0x03};
字符串[]firstCommandResponse=processCommand(firstCommand);
byte[]secondCommand=新字节[]{(字节)0x01,(字节)0x48,(字节)0x65,(字节)0x6C,(字节)0x6C,(字节)0x6F};
字符串[]secondCommandResponse=processCommand(secondCommand);
断开连接();
}捕获(例外e){
e、 printStackTrace();
}
}
公共空间断开连接()
{
试一试{
字节[]端连接=新字节[]{(字节)0x01,(字节)0x01,(字节)0x02,(字节)0x03};
processCommand(端连接);
dataOS.close();
dataIS.close();
sslSocket.close();
}捕获(例外e){
e、 printStackTrace();
}
}
公共字符串[]进程命令(字节[]命令)
{
字符串[]returnResponse=null;
字节[]命令响应=新字节[120];
字节[]表示命令响应;
试一试{
int-commandResponseLength=-1;
int errorCount=0;
while(commandResponseLength==-1)
{   
StringBuilder cmdStr=新建StringBuilder();
cmdStr.append(“发送:”);

对于(int i=0;i来说,这看起来实际上是JSSE实现的一个函数,它将数据拆分为两个数据包。第一个字节放在一个数据包中,其余字节放在下一个数据包中。更多详细信息,请参阅

您应该能够通过包括

System.setProperty("jsse.enableCBCProtection", "false");

看起来这实际上是JSSE实现的一个函数,它在两个数据包之间分割数据。第一个字节放在一个数据包中,其余的放在下一个数据包中

您应该能够通过包括

System.setProperty("jsse.enableCBCProtection", "false");

非常感谢。通过提供此详细信息,这将引导您使用以下方法来解决拆分数据包的问题:System.setProperty(“jsse.enableCBCProtection