如何从JavaHttpServer流式传输M-JPEG?

如何从JavaHttpServer流式传输M-JPEG?,java,http,mjpeg,Java,Http,Mjpeg,我试图从自定义视频源对象流式传输M-JPEG内容,但在查看wireshark的连接时,没有从服务器返回任何数据。下面是我使用的一些相关代码段。有人知道如何让这个代码运行吗 部分: try { server = new HTTPServerWrapper(8099); server.MJpegBindVideoSource(camera, "/test");

我试图从自定义视频源对象流式传输M-JPEG内容,但在查看wireshark的连接时,没有从服务器返回任何数据。下面是我使用的一些相关代码段。有人知道如何让这个代码运行吗

部分:

            try {
                server = new HTTPServerWrapper(8099);                
                server.MJpegBindVideoSource(camera, "/test");
            } catch (IOException ex) {
                Logger.getLogger(Recorder.class.getName()).log(Level.SEVERE, null, ex);
            }
physics/server/HTTPServerWrapper.java:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package physics.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import physics.VideoSource;

/**
 *
 * @author rritoch
 */
public class HTTPServerWrapper  {

    com.sun.net.httpserver.HttpServer server;

    public HTTPServerWrapper(int port) throws IOException{        
       server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(port), 0);                
    }

    public void MJpegBindVideoSource(VideoSource vs, String path) {        
        final VideoSource v = vs;        
        server.createContext(path,new MJpegHandler(vs)); 
    }    


}
physics/server/MJpegHandler.java:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package physics.server;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import physics.VideoSource;

/**
 *
 * @author rritoch
 */
public class MJpegHandler implements HttpHandler {

    VideoSource vs;

    public MJpegHandler(VideoSource videosource) {
        this.vs = videosource;
    }

    public void setVideoSource(VideoSource videosource) {
        this.vs = videosource;
    }

    public void handle(HttpExchange connection) throws IOException {
        byte[] data;

        System.err.println("Connect...");

        String boundary = "VNetPhysics";

        Headers responseHeaders = connection.getResponseHeaders();
        responseHeaders.add("Content-Type", String.format("multipart/x-mixed-replace; boundary=--%s", boundary));
        responseHeaders.add("Cache-Control", "no-cache, private");
        responseHeaders.add("Pragma", "no-cache");
        responseHeaders.add("Max-Age", "0");
        responseHeaders.add("Expires", "0");
        connection.sendResponseHeaders(200, 0);
        OutputStream responseBody = connection.getResponseBody();



        while (true) {

            BufferedImage bufferedImage = vs.getBufferedImage();

            ByteArrayOutputStream os = new ByteArrayOutputStream(8192 * 4);
            ImageIO.write(bufferedImage, "jpg", os);
            data = os.toByteArray();
            os.close();


            responseBody.write(("--" + boundary + "\r\n"
                    + "Content-type: image/jpg\r\n"
                    + "Content-Length: "
                    + data.length
                    + "\r\n\r\n").getBytes());

            responseBody.write(data);
            responseBody.flush();
        }

    }
};

编辑:在将connect消息添加到stderr之后,对http://192.168.2.7:8099/test的请求似乎没有被定向到此处理程序,因为没有处理程序,我可以理解为什么它不起作用。让这个处理程序来处理请求,我缺少了什么?

我看到这个问题已经问了两年了,但我还是会发布我的答案,以防人们在这里搜索和找到。。。我是这样做的

import org.mortbay.util.MultiPartOutputStream;
import org.w3c.www.mime.MultipartInputStream;
//其他东西

public static int searchFor(byte[] array, byte[] subArray) {
    if (subArray.length > array.length)
        return -1;
    int p = (new String(array)).indexOf(new String(subArray));
    for (int i = 1; i < subArray.length; i++) {
        if (array[p + i] != subArray[i])
            return -1;
    }
    return p;
}

public static int searchFor(byte[] array, byte[] subArray, int off) {
    if (subArray.length > array.length)
        return -1;
    int p = (new String(array)).indexOf(new String(subArray), off);
    for (int i = 1; i < subArray.length; i++) {
        if (array[p + i] != subArray[i])
            return -1;
    }
    return p;
}

@GET
@Path("getcamlistfromip")
@Produces("multipart/image")
public Response getcamlist(@Context UriInfo info, @Context HttpServletResponse response){
    String host = "192.168.1.155:8080";
    String link = "mjpeg1";
    HttpURLConnection con = null;
    InputStream in = null;
    OutputStream outstream = null;
    final String fullURL = "http://" + host + "/" + link;

    try {

        outstream = response.getOutputStream();

        URL url = new URL(fullURL);
        con = (HttpURLConnection) url.openConnection();
        con.setConnectTimeout(35000);
        con.setReadTimeout(35000);
        int rc = con.getResponseCode();
        String ct = con.getHeaderField("Content-Type");
        int inbounds = ct.indexOf("boundary=--");
        String inbound = ct.substring(inbounds + "boundary=--".length());
        System.out.println("inbound: " + inbound);
        int cli = con.getContentLength();
        byte[] boundery = inbound.getBytes();
        byte[] buffer = new byte[1024]; // Adjust if you want
        int bytesRead;
        in = con.getInputStream();
        MultiPartOutputStream multiPartOutputStream = new MultiPartOutputStream(outstream);
        String bounderyS = multiPartOutputStream.getBoundary();
        response.addHeader("Transfer-Encoding", null);
        response.addHeader("Expires", "0");
        response.addHeader("Pragma", "no-cache");
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Content-Type", "multipart/x-mixed-replace;boundary=--"+bounderyS);
        MultipartInputStream multipartInputStream = new MultipartInputStream(in, boundery);

        boolean boundstart = true;
        while (multipartInputStream.nextInputStream()) {

            boundstart = true;
            while ((bytesRead = multipartInputStream.read(buffer)) != -1)
            {
                if (boundstart) {
                    byte[] tmpba = new byte[1024];

                    String searchString = "Content-Length: ";
                    int clstart = searchFor(buffer, searchString.getBytes());
                    clstart += searchString.getBytes().length;
                    int clend = searchFor(buffer, "\r\n".getBytes(), clstart);
                    String conlen = new String(Arrays.copyOfRange(buffer, clstart, clend));
                    String[] headers = new String[2];
                    headers[0] = "Access-Control-Allow-Origin: *";
                    headers[1] = "Content-length: " + conlen;
                    multiPartOutputStream.startPart("image/jpeg", headers);
                    buffer = Arrays.copyOfRange(buffer, clend + "\r\n\r\n".getBytes().length, buffer.length);

                    bytesRead = buffer.length;
                }
                multiPartOutputStream.write(buffer, 0, bytesRead);
                boundstart = false;
                buffer = new byte[1024];
            }
            multiPartOutputStream.flush();

        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        con.disconnect();
        try {
            outstream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    host = null;
    link = null;

    return Response.ok(outstream, MultiPartMediaTypes.MULTIPART_MIXED_TYPE).build();//it actually doesn't matter what you give here since code never reaches here.
}
公共静态整型搜索(字节[]数组,字节[]子数组){
if(subArray.length>array.length)
返回-1;
int p=(新字符串(数组)).indexOf(新字符串(子数组));
对于(int i=1;iarray.length)
返回-1;
int p=(新字符串(数组)).indexOf(新字符串(子数组),关闭);
对于(int i=1;i.length());
System.out.println(“入站:+入站”);
int cli=con.getContentLength();
byte[]boundery=inbound.getBytes();
byte[]buffer=新字节[1024];//如果需要,请调整
int字节读取;
in=con.getInputStream();
MultiPartOutputStream MultiPartOutputStream=新的MultiPartOutputStream(扩展流);
String bounderyS=multiPartOutputStream.getBoundary();
addHeader(“传输编码”,null);
addHeader(“到期”、“0”);
addHeader(“Pragma”,“无缓存”);
addHeader(“访问控制允许来源”,“*”);
addHeader(“内容类型”,“多部分/x-mixed-replace;边界=”+bounderyS);
MultipartInputStream MultipartInputStream=新的MultipartInputStream(in,boundery);
布尔值boundstart=true;
while(multipartInputStream.nextInputStream()){
boundstart=true;
而((bytesRead=multipartInputStream.read(buffer))!=-1)
{
如果(开始){
字节[]tmpba=新字节[1024];
String searchString=“内容长度:”;
int clstart=searchFor(缓冲区,searchString.getBytes());
clstart+=searchString.getBytes().length;
int-clend=searchFor(缓冲区“\r\n”.getBytes(),clstart);
String conlen=新字符串(Arrays.copyOfRange(buffer、clstart、clend));
字符串[]头=新字符串[2];
标头[0]=“访问控制允许来源:”;
标题[1]=“内容长度:”+conlen;
multiPartOutputStream.startPart(“图像/jpeg”,标题);
buffer=Arrays.copyOfRange(buffer,clend+“\r\n\r\n”.getBytes().length,buffer.length);
bytesRead=buffer.length;
}
multiPartOutputStream.write(缓冲区,0,字节读取);
boundstart=false;
缓冲区=新字节[1024];
}
multiPartOutputStream.flush();
}
}捕获(IOE异常){
e、 printStackTrace();
}最后{
试一试{
in.close();
}捕获(IOE异常){
e、 printStackTrace();
}
con.disconnect();
试一试{
exptream.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
host=null;
link=null;
返回Response.ok(outstream,MultiPartMediaTypes.MULTIPART_MIXED_TYPE).build();//实际上您在这里给出什么并不重要,因为代码永远不会到达这里。
}
其他人可能有不同的方法,可能使用我不知道的其他库,特别是多部分InputStream头处理部分? Multipart类实际上会自动处理其每个Bodypart的头部分,但就目前所知,它不适合流式处理


快乐的编码。

PSSH。。。“requestHeaders”不代表响应头。对于残余,你到底为什么要使用
while(true)
infinite循环?@BalusC,现在这很尴尬。。。但是谢谢你的帮助。无限循环是暂时的,直到我可以植入一些代码来跟踪连接状态。测试修复后的代码后,我会继续跟进。@BalusC,我仍然有同样的问题。我已经将问题缩小到没有调用处理程序这一事实。连接正在建立,所以我不知道为什么不调用处理程序来请求“GET/test HTTP/1.1”@BalusC,问题现在解决了。我从未给HttpServer.start()我打过电话