Docker Community Forums

Share and learn in the Docker community.

Docker encodeing issuue whentrying to fetch the output using socket getinputStream


(Ajmalrehman) #1

Hi All,

I am having hard time figuring out why the first line of the output is having some binary characters (please refer the image for output). we are getting output from docker using the socket inputstream. Following is my code which will give you better understanding of what I am trying to achieve. In my scenario i am running a java program using docker api , the java program requires some input at runtime for this i using the following which executes perfectly fine except only the first line of the output is having some characters as shown in the image.
[class1…]
package com.examenginedashboard.docker.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
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 Program.java  && java -cp . Program 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());
		  
		  //MyOwnSocketClass myownclass = My
		
		/*try {
			ws = new HttpHijack(new URI("http://127.0.0.1:2375/v1.19/exec/" + execCreateCmdResponse.getId() + "/start"));
			 String payload = "{\"Detach\": false,\"Tty\": false}";
		        ws.post(headers, payload);
		        String request = "rock";
		        //Thread.sleep(3000);
		        InputStream input = ws.send(request);
		        int expectedDataLength=1024;
		        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("UTF-8"));
		        String line;
		        while ((line = input.readLine()) != null) {
		            System.out.println(" Output.........."+line);
		            String finalputput = convertToUTF8(line);
			        System.out.println("Output....2 "+finalputput);
		        }
		        
		       DataInputStream datainput = new DataInputStream(input);
		        byte[] messageByte = new byte[1000];
		        boolean end = false;
		        String messageString = "";
		        int bytesRead = 0;
		        messageByte[0] = datainput.readByte();
	            messageByte[1] = datainput.readByte();
	            ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2);
	            int bytesToRead = byteBuffer.getShort();
	            System.out.println("About to read " + bytesToRead + " octets");
	            System.out.println("Message Byte .. "+messageByte.length);
	            while(!end)
	            {
	                bytesRead = input.read(messageByte);
	                System.out.println(" Byte to read  .. "+bytesRead);
	                if(bytesRead!=-1){
	                messageString += new String(messageByte, 0, bytesRead);
	                }else{
	                	 end = true;
	                }
	                if (messageString.length() == bytesToRead )
	                {
	                    end = true;
	                }
	            }
	            System.out.println("MESSAGE: " + messageString);
		        byte[] outputbytes = readBytes(input);
		        String result = new String(outputbytes, Charset.forName("utf-8"));
		        //String result = IOUtils.toString(input, StandardCharsets.UTF_8);
		        String result = new BufferedReader(new InputStreamReader(input,"utf-8"))
		        .lines().collect(Collectors.joining("\n"));
		        Reader read = new InputStreamReader(input);
		        String result;
		        StringBuilder sb = new StringBuilder();
		        char[] chars = new char [4*1024];
		        int len;
		        while((len=read.read(chars))>=0){
		        	sb.append(chars,0,len);
		        }
		        result = sb.toString();
		        //System.out.println("Request output......... "+result);
		} catch (URISyntaxException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} */

}
public static byte[] readBytes( InputStream stream ) throws IOException {
if (stream == null) return new byte[] {};
byte[] buffer = new byte[1024];
ByteArrayOutputStream output = new ByteArrayOutputStream();
boolean error = false;
try {
int numRead = 0;
while ((numRead = stream.read(buffer)) > -1) {
output.write(buffer, 0, numRead);
}
} catch (IOException e) {
error = true; // this error should be thrown, even if there is an error closing stream
throw e;
} catch (RuntimeException e) {
error = true; // this error should be thrown, even if there is an error closing stream
throw e;
} finally {
try {
stream.close();
} catch (IOException e) {
if (!error) throw e;
}
}
output.flush();
return output.toByteArray();
}

	public  static String convertToUTF8(String s) {
        String out = null;
        out = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        return out;
    }
public static void main(String[] args){
	
	connectToDocker();
}
}

[Class2]

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();
    	//DataInputStream in = new DataInputStream(socket.getInputStream());
    	/*BufferedReader in = new BufferedReader(
    	        new InputStreamReader(socket.getInputStream()));*/
    	return socket.getInputStream();
    
}

public void close() throws java.io.IOException {
    chin.close();
    chout.close();
    socket.close();
}

}

Please suggest!
Thanks in advance.