从 socket.getInpitStream() 读取时返回的二进制字符
Binary characters returned when reading from socket.getInpitStream()
package com.examenginedashboard.docker.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import com.examenginedashboard.CONSTANTS.MyValuesConstans;
import com.examenginedashboard.codePG.service.HttpHijack;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.api.command.InspectExecResponse;
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.command.ExecStartResultCallback;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
public class APIBasedCodeCompiler {
public static void connectToDocker(){
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
.withReadTimeout(1000)
.withConnectTimeout(1000)
.withMaxTotalConnections(100)
.withMaxPerRouteConnections(10);
ExposedPort tcp22 = ExposedPort.tcp(22);
ExposedPort tcp23 = ExposedPort.tcp(23);
Ports portBindings = new Ports();
portBindings.bind(tcp22, Ports.Binding.bindPort(11022));
portBindings.bind(tcp23, Ports.Binding.bindPort(11023));
DockerClientConfig config = DefaultDockerClientConfig. createDefaultConfigBuilder()
.withDockerHost("tcp://127.0.0.1:2375")
.build();
DockerClient docker = DockerClientBuilder.getInstance(config).build();
Volume volume1 = new Volume("/mydockerbuild");
CreateContainerResponse containerResp = docker.createContainerCmd("busybox")
.withImage(MyValuesConstans.JAVA_DOCKER)
.withCmd("sh", "-c", "while :; do sleep 1; done")
.withAttachStderr(true)
.withAttachStdout(true)
.withAttachStdin(true)
.withVolumes(volume1)
.withBinds(new Bind("/home/itcostcut/mydockerbuild",volume1))
.exec();
String containerId = containerResp.getId();
docker.startContainerCmd(containerId).exec();
System.out.println("HOST........... ");
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
final String[] command = {"bash", "-c", "cd mydockerbuild/ && javac NumberToWord.java && java -cp . NumberToWord exit"};
ExecCreateCmdResponse execCreateCmdResponse = docker.execCreateCmd(containerId)
.withAttachStdout(true)
.withAttachStderr(true)
.withAttachStdin(true)
.withCmd(command)
.exec();
InspectExecResponse inpect = docker.inspectExecCmd(execCreateCmdResponse.getId()).exec();
System.out.println("Inspect Info........... "+inpect);
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
HttpHijack ws;
// http://localhost:4243
//unix:///var/run/docker.sock
docker.execStartCmd(execCreateCmdResponse.getId()).exec(
new ExecStartResultCallback(stdout, stderr));
System.out.println("Output: "+stdout.toString());
System.out.println("Error: "+stderr.toString());
try {
ws = new HttpHijack(new URI("http://127.0.0.1:2375/v1.27/exec/" + execCreateCmdResponse.getId() + "/start"));
String payload = "{\"Detach\": false,\"Tty\": false}";
ws.post(headers, payload);
String request = "10";
//Thread.sleep(3000);
InputStream input = ws.send(request);
int expectedDataLength=5000;
ByteArrayOutputStream baos = new ByteArrayOutputStream(expectedDataLength);
byte[] chunk = new byte[expectedDataLength];
int numBytesJustRead;
while((numBytesJustRead = input.read(chunk)) != -1) {
baos.write(chunk, 0, numBytesJustRead);
}
System.out.println("Result ............... "+baos.toString());
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
public static void main(String[] args){
connectToDocker();
}}
下面是连接到 Java Docker 的 HttpHijack.java class。
package com.examenginedashboard.codePG.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpHijack {
private static final Logger log = LoggerFactory. getLogger(HttpHijack.class);
private URI uri;
private Socket socket;
private boolean handshakeCompleted;
private InputStream chin;
private OutputStream chout;
public HttpHijack(URI url) {
uri = url;
}
public void post(Map<String, String> headers, String payload) throws java.io.IOException {
String host = uri.getHost();
System.out.println("Hostname ........."+host);
String path = uri.getPath();
System.out.println("Path..............."+path);
if (path.equals("")) {
path = "/";
}
String query = uri.getQuery();
System.out.println("Query................"+query);
if (query != null) {
path = path + "?" + query;
}
socket = createSocket();
chout = socket.getOutputStream();
StringBuffer extraHeaders = new StringBuffer();
if (headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
extraHeaders.append(entry.getKey() + ": " + entry.getValue() + "\r\n");
}
}
StringBuffer request = new StringBuffer();
request.append("POST " + path + " HTTP/1.1\r\n");
request.append("Upgrade: tcp\r\n");
request.append("Connection: Upgrade\r\n");
request.append("Host: " + host + "\r\n");
if (headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
request.append(entry.getKey() + ": " + entry.getValue() + "\r\n");
}
}
request.append("Content-Length: " + payload.length() + "\r\n");
request.append("\r\n");
request.append(payload);
chout.write(request.toString().getBytes());
chout.flush();
chin = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(chin));
String header = reader.readLine();
if (!header.equals("HTTP/1.1 101 UPGRADED")) {
throw new IOException("Invalid handshake response: " + header);
}
do {
header = reader.readLine();
log.info("header: {}", header);
} while (!header.equals(""));
handshakeCompleted = true;
}
private Socket createSocket() throws java.io.IOException {
String scheme = uri.getScheme();
String host = uri.getHost();
int port = uri.getPort();
if (port == -1) {
if (scheme.equals("https")) {
port = 443;
} else if (scheme.equals("http")) {
port = 80;
} else {
throw new IllegalArgumentException("Unsupported scheme");
}
}
if (scheme.equals("https")) {
SocketFactory factory = SSLSocketFactory.getDefault();
return factory.createSocket(host, port);
} else {
return new Socket(host, port);
}
}
public InputStream send(String command) throws java.io.IOException {
if (!handshakeCompleted) {
throw new IllegalStateException("Handshake not complete");
}
chout.write(command.getBytes(StandardCharsets.UTF_8));
System.out.println("Input Bytes ...... "+command.getBytes("UTF-8"));
chout.flush();
// looks like "exit" can't explicitly close the session,
// shutdown output stream to force close it
// so that stdout/stderr can be consumed via inputstream
socket.shutdownOutput();
System.out.println("Socket String .............. "+socket.toString());
return socket.getInputStream();
}
public void close() throws java.io.IOException {
chin.close();
chout.close();
socket.close();
}}
我将尝试解释我想要实现的目标。在我的场景中,我试图在 docker 上执行一些 Java 程序,因为我使用了 Java:7 docker 图像。
命令 = {"bash", "-c", "cd mydockerbuild/ && javac NumberToWord.java && java -cp . NumberToWord exit"};用于 运行 宁 java 代码和 NumberToWord.java 是 java class。我们可以将任何 java 代码带到 运行 但它应该需要一些输入才能执行,在我的情况下用户输入是 10.
问题是当我从 socket.getInputStream 读取输出时,输出的某些行是二进制字符,请参阅下面的日志。
May 27, 2017 3:46:14 PM com.examenginedashboard.codePG.
service.HttpHijack post
INFO: header: Content-Type: application/vnd.
docker.raw-stream
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Connection: Upgrade
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Upgrade: tcp
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Api-Version: 1.27
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Docker-Experimental: false
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Server: Docker/17.03.1-ce (linux)
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header:
Input Bytes ...... [B@6436a7db
Socket String .............. Socket[addr=/127.0.0.1,port=2375,
localport=60804]
Result ...............
实际输出如图所示Final Output Here
问题出在 docker 原始流上。它将 stdoud
和 stderr
复用到一个通道中。为此,在每一位内容之前,它发送一个 8 位 header.
- 如果以下内容为stdout,则第一位为1,stderr为2,stdin为0。
- 第二位、第三位和第四位始终为零
- 最后4位是big endian中内容的长度。
要对此进行解码,请执行以下操作:
- 阅读header
- 确定内容长度
- 阅读内容(注意,即使内容是针对stderr的,我们不想要它,我们仍然需要阅读它)。
- 如果内容是实际内容,将其添加到缓冲区
以下测试针对您提供的数组执行此操作:
public static void main(String[] args) throws FileNotFoundException, IOException {
byte[] data = new byte[] {1, 0, 0, 0, 0, 0, 0, 102, 89, 111, 117, 114, 32, 119, 111, 114, 100, 115, 32, 97, 114, 101, 32, 104, 101, 114, 101, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 32, 33, 33, 10, 89, 111, 117, 114, 32, 119, 111, 114, 100, 115, 32, 97, 114, 101, 32, 104, 101, 114, 101, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 32, 33, 33, 10, 89, 111, 117, 114, 32, 119, 111, 114, 100, 115, 32, 97, 114, 101, 32, 104, 101, 114, 101, 46, 46, 46, 46, 46, 46, 46, 46, 46,46, 46, 32, 33, 33, 10, 1, 0, 0, 0, 0, 0, 0, 21, 105, 110, 112, 117, 116, 32, 105, 110, 32, 87, 111, 114, 100, 115, 32, 58, 32, 32, 84, 101, 110, 1, 0, 0, 0, 0, 0, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 19, 67, 79, 77, 69, 32, 79, 78, 32, 76, 73, 75, 69, 32, 73, 84, 32, 33, 33, 10};
InputStream is = new ByteArrayInputStream(data); //I just created this for testing
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] header = new byte[8];
while(true){
if(!readFully(is, header, 8)) break;
int contentSize = ((header[4] & 0xFF) << 24) | ((header[5] & 0xFF) << 16)
| ((header[6] & 0xFF) << 8) | (header[7] & 0xFF);
boolean actualContent = header[0] == 1;
byte[] content = new byte[contentSize];
if(!readFully(is, content, contentSize))break;
if(actualContent)
baos.write(content, 0, contentSize);
else
System.err.println(new String(content));
}
System.out.println(baos.toString());
}
/**
* Read a given number of bytes from the stream and store them in the buffer.
*
* @param is
* The input stream to read from
* @param buffer
* The buffer to store it in
* @size size
* The number of bytes to read
*
* @return True if and only if all bytes were read.
*/
public static boolean readFully(InputStream is, byte[] buffer, int size) throws IOException{
int totalAmountRead = 0;
while(totalAmountRead < size){
int amountJustRead = is.read(buffer, totalAmountRead, size-totalAmountRead);
if(amountJustRead == -1)
return false;
totalAmountRead += amountJustRead;
}
return true;
}
这给出了输出:
Your words are here........... !!
Your words are here........... !!
Your words are here........... !!
input in Words : Ten
COME ON LIKE IT !!
package com.examenginedashboard.docker.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import com.examenginedashboard.CONSTANTS.MyValuesConstans;
import com.examenginedashboard.codePG.service.HttpHijack;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.api.command.InspectExecResponse;
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.command.ExecStartResultCallback;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
public class APIBasedCodeCompiler {
public static void connectToDocker(){
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
.withReadTimeout(1000)
.withConnectTimeout(1000)
.withMaxTotalConnections(100)
.withMaxPerRouteConnections(10);
ExposedPort tcp22 = ExposedPort.tcp(22);
ExposedPort tcp23 = ExposedPort.tcp(23);
Ports portBindings = new Ports();
portBindings.bind(tcp22, Ports.Binding.bindPort(11022));
portBindings.bind(tcp23, Ports.Binding.bindPort(11023));
DockerClientConfig config = DefaultDockerClientConfig. createDefaultConfigBuilder()
.withDockerHost("tcp://127.0.0.1:2375")
.build();
DockerClient docker = DockerClientBuilder.getInstance(config).build();
Volume volume1 = new Volume("/mydockerbuild");
CreateContainerResponse containerResp = docker.createContainerCmd("busybox")
.withImage(MyValuesConstans.JAVA_DOCKER)
.withCmd("sh", "-c", "while :; do sleep 1; done")
.withAttachStderr(true)
.withAttachStdout(true)
.withAttachStdin(true)
.withVolumes(volume1)
.withBinds(new Bind("/home/itcostcut/mydockerbuild",volume1))
.exec();
String containerId = containerResp.getId();
docker.startContainerCmd(containerId).exec();
System.out.println("HOST........... ");
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
final String[] command = {"bash", "-c", "cd mydockerbuild/ && javac NumberToWord.java && java -cp . NumberToWord exit"};
ExecCreateCmdResponse execCreateCmdResponse = docker.execCreateCmd(containerId)
.withAttachStdout(true)
.withAttachStderr(true)
.withAttachStdin(true)
.withCmd(command)
.exec();
InspectExecResponse inpect = docker.inspectExecCmd(execCreateCmdResponse.getId()).exec();
System.out.println("Inspect Info........... "+inpect);
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
HttpHijack ws;
// http://localhost:4243
//unix:///var/run/docker.sock
docker.execStartCmd(execCreateCmdResponse.getId()).exec(
new ExecStartResultCallback(stdout, stderr));
System.out.println("Output: "+stdout.toString());
System.out.println("Error: "+stderr.toString());
try {
ws = new HttpHijack(new URI("http://127.0.0.1:2375/v1.27/exec/" + execCreateCmdResponse.getId() + "/start"));
String payload = "{\"Detach\": false,\"Tty\": false}";
ws.post(headers, payload);
String request = "10";
//Thread.sleep(3000);
InputStream input = ws.send(request);
int expectedDataLength=5000;
ByteArrayOutputStream baos = new ByteArrayOutputStream(expectedDataLength);
byte[] chunk = new byte[expectedDataLength];
int numBytesJustRead;
while((numBytesJustRead = input.read(chunk)) != -1) {
baos.write(chunk, 0, numBytesJustRead);
}
System.out.println("Result ............... "+baos.toString());
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
public static void main(String[] args){
connectToDocker();
}}
下面是连接到 Java Docker 的 HttpHijack.java class。
package com.examenginedashboard.codePG.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpHijack {
private static final Logger log = LoggerFactory. getLogger(HttpHijack.class);
private URI uri;
private Socket socket;
private boolean handshakeCompleted;
private InputStream chin;
private OutputStream chout;
public HttpHijack(URI url) {
uri = url;
}
public void post(Map<String, String> headers, String payload) throws java.io.IOException {
String host = uri.getHost();
System.out.println("Hostname ........."+host);
String path = uri.getPath();
System.out.println("Path..............."+path);
if (path.equals("")) {
path = "/";
}
String query = uri.getQuery();
System.out.println("Query................"+query);
if (query != null) {
path = path + "?" + query;
}
socket = createSocket();
chout = socket.getOutputStream();
StringBuffer extraHeaders = new StringBuffer();
if (headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
extraHeaders.append(entry.getKey() + ": " + entry.getValue() + "\r\n");
}
}
StringBuffer request = new StringBuffer();
request.append("POST " + path + " HTTP/1.1\r\n");
request.append("Upgrade: tcp\r\n");
request.append("Connection: Upgrade\r\n");
request.append("Host: " + host + "\r\n");
if (headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
request.append(entry.getKey() + ": " + entry.getValue() + "\r\n");
}
}
request.append("Content-Length: " + payload.length() + "\r\n");
request.append("\r\n");
request.append(payload);
chout.write(request.toString().getBytes());
chout.flush();
chin = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(chin));
String header = reader.readLine();
if (!header.equals("HTTP/1.1 101 UPGRADED")) {
throw new IOException("Invalid handshake response: " + header);
}
do {
header = reader.readLine();
log.info("header: {}", header);
} while (!header.equals(""));
handshakeCompleted = true;
}
private Socket createSocket() throws java.io.IOException {
String scheme = uri.getScheme();
String host = uri.getHost();
int port = uri.getPort();
if (port == -1) {
if (scheme.equals("https")) {
port = 443;
} else if (scheme.equals("http")) {
port = 80;
} else {
throw new IllegalArgumentException("Unsupported scheme");
}
}
if (scheme.equals("https")) {
SocketFactory factory = SSLSocketFactory.getDefault();
return factory.createSocket(host, port);
} else {
return new Socket(host, port);
}
}
public InputStream send(String command) throws java.io.IOException {
if (!handshakeCompleted) {
throw new IllegalStateException("Handshake not complete");
}
chout.write(command.getBytes(StandardCharsets.UTF_8));
System.out.println("Input Bytes ...... "+command.getBytes("UTF-8"));
chout.flush();
// looks like "exit" can't explicitly close the session,
// shutdown output stream to force close it
// so that stdout/stderr can be consumed via inputstream
socket.shutdownOutput();
System.out.println("Socket String .............. "+socket.toString());
return socket.getInputStream();
}
public void close() throws java.io.IOException {
chin.close();
chout.close();
socket.close();
}}
我将尝试解释我想要实现的目标。在我的场景中,我试图在 docker 上执行一些 Java 程序,因为我使用了 Java:7 docker 图像。 命令 = {"bash", "-c", "cd mydockerbuild/ && javac NumberToWord.java && java -cp . NumberToWord exit"};用于 运行 宁 java 代码和 NumberToWord.java 是 java class。我们可以将任何 java 代码带到 运行 但它应该需要一些输入才能执行,在我的情况下用户输入是 10.
问题是当我从 socket.getInputStream 读取输出时,输出的某些行是二进制字符,请参阅下面的日志。
May 27, 2017 3:46:14 PM com.examenginedashboard.codePG.
service.HttpHijack post
INFO: header: Content-Type: application/vnd.
docker.raw-stream
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Connection: Upgrade
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Upgrade: tcp
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Api-Version: 1.27
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Docker-Experimental: false
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header: Server: Docker/17.03.1-ce (linux)
May 27, 2017 3:46:14 PM com.examenginedashboard.
codePG.service.HttpHijack post
INFO: header:
Input Bytes ...... [B@6436a7db
Socket String .............. Socket[addr=/127.0.0.1,port=2375,
localport=60804]
Result ...............
实际输出如图所示Final Output Here
问题出在 docker 原始流上。它将 stdoud
和 stderr
复用到一个通道中。为此,在每一位内容之前,它发送一个 8 位 header.
- 如果以下内容为stdout,则第一位为1,stderr为2,stdin为0。
- 第二位、第三位和第四位始终为零
- 最后4位是big endian中内容的长度。
要对此进行解码,请执行以下操作:
- 阅读header
- 确定内容长度
- 阅读内容(注意,即使内容是针对stderr的,我们不想要它,我们仍然需要阅读它)。
- 如果内容是实际内容,将其添加到缓冲区
以下测试针对您提供的数组执行此操作:
public static void main(String[] args) throws FileNotFoundException, IOException {
byte[] data = new byte[] {1, 0, 0, 0, 0, 0, 0, 102, 89, 111, 117, 114, 32, 119, 111, 114, 100, 115, 32, 97, 114, 101, 32, 104, 101, 114, 101, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 32, 33, 33, 10, 89, 111, 117, 114, 32, 119, 111, 114, 100, 115, 32, 97, 114, 101, 32, 104, 101, 114, 101, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 32, 33, 33, 10, 89, 111, 117, 114, 32, 119, 111, 114, 100, 115, 32, 97, 114, 101, 32, 104, 101, 114, 101, 46, 46, 46, 46, 46, 46, 46, 46, 46,46, 46, 32, 33, 33, 10, 1, 0, 0, 0, 0, 0, 0, 21, 105, 110, 112, 117, 116, 32, 105, 110, 32, 87, 111, 114, 100, 115, 32, 58, 32, 32, 84, 101, 110, 1, 0, 0, 0, 0, 0, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 19, 67, 79, 77, 69, 32, 79, 78, 32, 76, 73, 75, 69, 32, 73, 84, 32, 33, 33, 10};
InputStream is = new ByteArrayInputStream(data); //I just created this for testing
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] header = new byte[8];
while(true){
if(!readFully(is, header, 8)) break;
int contentSize = ((header[4] & 0xFF) << 24) | ((header[5] & 0xFF) << 16)
| ((header[6] & 0xFF) << 8) | (header[7] & 0xFF);
boolean actualContent = header[0] == 1;
byte[] content = new byte[contentSize];
if(!readFully(is, content, contentSize))break;
if(actualContent)
baos.write(content, 0, contentSize);
else
System.err.println(new String(content));
}
System.out.println(baos.toString());
}
/**
* Read a given number of bytes from the stream and store them in the buffer.
*
* @param is
* The input stream to read from
* @param buffer
* The buffer to store it in
* @size size
* The number of bytes to read
*
* @return True if and only if all bytes were read.
*/
public static boolean readFully(InputStream is, byte[] buffer, int size) throws IOException{
int totalAmountRead = 0;
while(totalAmountRead < size){
int amountJustRead = is.read(buffer, totalAmountRead, size-totalAmountRead);
if(amountJustRead == -1)
return false;
totalAmountRead += amountJustRead;
}
return true;
}
这给出了输出:
Your words are here........... !!
Your words are here........... !!
Your words are here........... !!
input in Words : Ten
COME ON LIKE IT !!