socket : 使用定时器获取二进制图像

发布于 2024-11-05 21:47:40 字数 4986 浏览 0 评论 0原文

我正在尝试通过客户端从服务器获取多个图像。

我的最终目标是通过套接字(在同一台计算机上)从Java程序中的C++程序和Ogre生成的电影中获取图像,因为JNI对我来说似乎非常困难。

为了尝试一下,我在java下做了一个客户端/服务器,只是为了测试,但效果不佳。事实上,结果是相当随机的,我有时会得到 2 个、有时 4 个图像,但从来不会得到全部。

我认为我的流没有很好地同步,我也想知道 UDP 是否不能更合适,但我不知道该怎么做。

这是我使用的代码:

public class Client {

static final int port = 3334;
static final String host = "aluminod";
public static final double STEP = 2000.0;
public static final int DELAY = 0;

private Socket socket;
private PrintWriter printWriter;
private BufferedReader input;
private int imgNumber = 0;
private static MoviePanel pane;
private Timer timer;

public Client() throws UnknownHostException, IOException{
    this.socket = new Socket(host, port);
    System.out.println("SOCKET = " + socket);
    this.printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
    this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    start();
}

public static void main(String[] args){
    JFrame frame = new JFrame("test");
    pane = new MoviePanel();
    frame.setPreferredSize(new Dimension(600,400));
    frame.setSize(new Dimension(600,400));
    frame.setVisible(true);
    frame.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width/2-300, Toolkit.getDefaultToolkit().getScreenSize().height/2-200);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(pane, BorderLayout.CENTER);
    frame.add(pane);


    try {
        new Client();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private void start(){
    this.timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            try {
                sendParamsToVC();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }, DELAY, (long) STEP);
}

private void sendParamsToVC() throws IOException {
    System.out.println("---sending---");
    String mess = buildMessage();


    //envoi du message au serveur
    printWriter.println(mess);

    // lecture de la réponse du serveur
    InputStream is = socket.getInputStream();
    int taille = Integer.parseInt(input.readLine());
    byte[] mybytearray = new byte[taille];
    is.read(mybytearray, 0, taille);    
    BufferedImage img = ImageIO.read(new ByteArrayInputStream(mybytearray));

    pane.change(img);
    imgNumber++;
}

private String buildMessage(){
    String mess;
    if(imgNumber <10)mess = "000"+imgNumber;
    else if(imgNumber<=13)mess = "00"+imgNumber;
    else {
        mess = "NO_IMG";
        timer.cancel();
    }
    return mess;

}

}

public class Server {
static final int port = 3334;

public static void main(String[] args) throws Exception {
    ServerSocket servsocket = new ServerSocket(port); 
    while (true) {
        Socket client = servsocket.accept();
        System.out.println("connection accepted");

        BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
        BufferedOutputStream output = new BufferedOutputStream(client.getOutputStream());

        while (true) {
            String str = reader.readLine();          // lecture du message
            if (str.equals("NO_IMG")){
                System.out.println("ECHO = " + str);
                System.out.println("fermeture");
                break;
            }
            System.out.println("ECHO = " + str);   // trace locale

            //renvoi de l'image
            OutputStream os = client.getOutputStream();
            byte[]data = getByteFromImage(str);
            PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
            writer.println(data.length);
            writer.flush();
            os.write(data, 0, data.length);
            os.flush();

        }
        output.close();
        reader.close();
        client.close();
    }
}

public static byte[] getByteFromImage(String numImage) {        

    BufferedImage img = ImageLoader.createBufferedImage(numImage);

    /** On crée la nouvelle image */
    BufferedImage bufferedImage = new BufferedImage(
                img.getWidth(null),
                img.getHeight(null),
                BufferedImage.TYPE_INT_BGR );
    Graphics g = bufferedImage.createGraphics();
    g.drawImage(img,0,0,null);
    g.dispose();             
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try {
        ImageIO.write(bufferedImage, "jpeg", out);
        out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }

    byte buffer[] = out.toByteArray();

    try {
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return (buffer);
}

}

I'm trying to get multiple images from a server with a client.

My ultimate goal is to get images from a movie generated by a C++ program with Ogre in a Java program by sockets (on the same computer), because JNI seems very difficult to me.

To try it, i made a client/server both under java, just for test, but it doesn't work well. In fact, the result is pretty random and i get sometimes 2, sometimes 4 images, but never all.

I think my streams are not well synchronized, and i was wondering too if UDP couldn't be more appropriated, but i don't know how to do it.

Here are the codes i use :

public class Client {

static final int port = 3334;
static final String host = "aluminod";
public static final double STEP = 2000.0;
public static final int DELAY = 0;

private Socket socket;
private PrintWriter printWriter;
private BufferedReader input;
private int imgNumber = 0;
private static MoviePanel pane;
private Timer timer;

public Client() throws UnknownHostException, IOException{
    this.socket = new Socket(host, port);
    System.out.println("SOCKET = " + socket);
    this.printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
    this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    start();
}

public static void main(String[] args){
    JFrame frame = new JFrame("test");
    pane = new MoviePanel();
    frame.setPreferredSize(new Dimension(600,400));
    frame.setSize(new Dimension(600,400));
    frame.setVisible(true);
    frame.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width/2-300, Toolkit.getDefaultToolkit().getScreenSize().height/2-200);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(pane, BorderLayout.CENTER);
    frame.add(pane);


    try {
        new Client();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private void start(){
    this.timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            try {
                sendParamsToVC();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }, DELAY, (long) STEP);
}

private void sendParamsToVC() throws IOException {
    System.out.println("---sending---");
    String mess = buildMessage();


    //envoi du message au serveur
    printWriter.println(mess);

    // lecture de la réponse du serveur
    InputStream is = socket.getInputStream();
    int taille = Integer.parseInt(input.readLine());
    byte[] mybytearray = new byte[taille];
    is.read(mybytearray, 0, taille);    
    BufferedImage img = ImageIO.read(new ByteArrayInputStream(mybytearray));

    pane.change(img);
    imgNumber++;
}

private String buildMessage(){
    String mess;
    if(imgNumber <10)mess = "000"+imgNumber;
    else if(imgNumber<=13)mess = "00"+imgNumber;
    else {
        mess = "NO_IMG";
        timer.cancel();
    }
    return mess;

}

}

public class Server {
static final int port = 3334;

public static void main(String[] args) throws Exception {
    ServerSocket servsocket = new ServerSocket(port); 
    while (true) {
        Socket client = servsocket.accept();
        System.out.println("connection accepted");

        BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
        BufferedOutputStream output = new BufferedOutputStream(client.getOutputStream());

        while (true) {
            String str = reader.readLine();          // lecture du message
            if (str.equals("NO_IMG")){
                System.out.println("ECHO = " + str);
                System.out.println("fermeture");
                break;
            }
            System.out.println("ECHO = " + str);   // trace locale

            //renvoi de l'image
            OutputStream os = client.getOutputStream();
            byte[]data = getByteFromImage(str);
            PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
            writer.println(data.length);
            writer.flush();
            os.write(data, 0, data.length);
            os.flush();

        }
        output.close();
        reader.close();
        client.close();
    }
}

public static byte[] getByteFromImage(String numImage) {        

    BufferedImage img = ImageLoader.createBufferedImage(numImage);

    /** On crée la nouvelle image */
    BufferedImage bufferedImage = new BufferedImage(
                img.getWidth(null),
                img.getHeight(null),
                BufferedImage.TYPE_INT_BGR );
    Graphics g = bufferedImage.createGraphics();
    g.drawImage(img,0,0,null);
    g.dispose();             
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try {
        ImageIO.write(bufferedImage, "jpeg", out);
        out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }

    byte buffer[] = out.toByteArray();

    try {
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return (buffer);
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

兔小萌 2024-11-12 21:47:40

读取器/写入器流用于字符数据。不要将它们用于二进制数据。使用(缓冲)InputStream/OutputStream

编辑:忘记我上面所说的。我检查了您的其余代码,看起来您正在混合流,并且客户端在发送命令时不会刷新流。这意味着可以在客户端进行缓冲。

Edit2:另一个错误是您没有检查 read 返回的内容。它返回一个 int 值,表示您已收到多少字节。这并不总是与您的缓冲区大小相同。它可以更少。你需要处理这个问题。

The reader/writer streams are for character data. Don't use them for binary data. Use (Buffered)InputStream/OutputStream

Edit: Forget what I said above. I checked the rest of your code, and it looks like you are mixing streams, and the client isn't flushing the stream when it sends commands. The means that is can be buffered on the client.

Edit2: Another error is that you don't check what read returns. It returns an int that says home many bytes you have received. That isn't always the same as your buffer size. It can be less. You need to handle that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文