1

ソケットを介してクライアントに画像をバイト配列として送信して、画像を表示できるようにしようとしていますが、断片化された画像を表示する場合を除いてすべてうまくいきます。画像の上位10番目を表示できますが、残りは灰色と黒のピクセルが表示され、その理由がわかりません

私のサーバーコードの一部です:

    public synchronized void nextFrame(VideoFrame frame) {
        // This method is called when a new frame is ready.
        // Don't forget to recycle it when done dealing with the frame.

        // draw the new frame onto the JLabel
            go = true;
            pic = frame.getBytes();
            go = false;
            label.getGraphics().drawImage(frame.getBufferedImage(), 0, 0, width, height, null);
            frame.recycle();

    }
}

class server extends Thread{
    int port;
    ServerSocket socket;
    Socket temps = null;
    boolean go = true;
    server(int p){
        port = p;
        start();
    }

    public void run(){      

        while(go == true){
            try {
                socket = new ServerSocket(port, 10);
                socket.setSoTimeout(10000);
                temps = socket.accept();
                new connect(temps);
                port += 1;
            } catch (IOException e) {
                if(e.getMessage().toString().equalsIgnoreCase("Accept timed out")){
                    go = false;
                }else{
                    e.printStackTrace();
                }
                break;
            }

        }
        try {
            socket.close();
            System.out.println("Closing socket server(no more connections will be created)");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class connect extends Thread{
    Socket connection;
    ObjectOutputStream out;
    int port;
    String host;
    GetInput in;
    connect(Socket s){
        try {
            connection = s;
            out = new ObjectOutputStream(connection.getOutputStream());
            host = connection.getInetAddress().getHostName();
            port = connection.getPort();
            System.out.println("Connected to " + host + ":" + port);
            in = new GetInput(connection);
            start();
        } catch (IOException e) {
            e.printStackTrace();
        }   
    }

    public void run(){
        try {
            out.writeInt(Main.pic.length);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        while(in.isAlive()){
            if(Main.go){    
                try {
                    out.write(Main.pic);
                } catch (IOException e) {
                        e.getMessage().toString();
                }
            }
        }
        try {
            out.close();
            connection.close();
            System.out.println("Closing " + host + ":" + port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class GetInput extends Thread{
    ObjectInputStream in;
    GetInput(Socket s){
        try {
            in = new ObjectInputStream(s.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        start();
    }
    public void run(){
        try{
            boolean go = in.readBoolean();
            int a = (go?1:0);
            System.out.println(a);
        } catch (IOException e) {
                e.getMessage().toString();
        }
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

フレームグラバーが画像を正しく取得していることはわかっています。これは、サーバー上に画像も表示していて、見た目が良いため、バイト配列がソケットを介して正しく送信されていないことを意味しますが、なぜですか?

編集:私のクライアントコード、それはAndroidアプリです

package org.smiley.doom;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

public class ClientActivity extends Activity implements View.OnClickListener{

    Socket s;
    InetAddress inet;
    ObjectOutputStream out;
    ObjectInputStream in;
    TextView log;
    ImageView im;
    Button send;
    EditText tip;
    int rport;
    String ip;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tip = (EditText) findViewById(R.id.etIP);
        send = (Button) findViewById(R.id.bSEND);
        im = (ImageView) findViewById(R.id.ivPIC);
        log = (TextView) findViewById(R.id.tvLog);

        s = null;
        in = null;
        out = null;

        send.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0) {
        switch(arg0.getId()){
            case R.id.bSEND:
                final int len;
                    try {
                        inet = InetAddress.getByName("192.168.0.2");
                        s = new Socket(inet, 4321);
                        in = new ObjectInputStream(s.getInputStream());
                        out = new ObjectOutputStream(s.getOutputStream());
                        log.setText("Client opened");
                        len = in.readInt();
                        new Thread(new Runnable(){

                            @Override
                            public void run() {
                                    byte[] b = new byte[len];
                                    try {
                                        in.read(b);
                                        log.setText(""+s.getReceiveBufferSize());
                                    } catch (IOException e1) {
                                        e1.printStackTrace();
                                    }
                                    final byte[] l = b;
                                    im.post(new Runnable(){
                                        @Override
                                        public void run() {
                                            Bitmap bmp = BitmapFactory.decodeByteArray(l, 0, l.length);
                                            im.setImageBitmap(bmp);                             
                                        }
                                    });
                                    try {
                                        out.writeBoolean(true);
                                        out.close();
                                        in.close();
                                        s.close();
                                        //log.setText("Client closed");
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                            }

                        }).start();;
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            break;
        }
    }
}
4

3 に答える 3

3

TCPは、現在利用可能なバイト数だけをアプリケーションに配信します。基盤となるネットワーク層(IP)はパケットベースであるため、送信中にストリームが部分的にチャンク化されます。受信側のネットワークスタックは、これらのチャンク(パケット)をネットワークカードから取得し、アプリケーションが特定のソケットから読み取るまでそれらをバッファリングします。その時点minで、バッファサイズと、OSのソケットごとのバッファに積み上げられたものを取得します。

TCP接続はストリームを表すため、OSはアプリケーションメッセージについて何も認識しません。したがって、すべてを再構築するのはユーザーの責任です。

すべてのデータがあることがわかるまで、ループでソケットから読み取る必要があります。これを知る最も簡単な方法は、送信するバイト数を事前にクライアントに通知することです。

于 2012-07-26T18:31:49.837 に答える
0

データ セグメント (画像) がバッファーよりもはるかに大きい可能性があります。

どういうわけか、書き込みバッファーがオーバーフローする前に出力をフラッシュできるように、出力をバッファーする方法を見つける必要があります。

于 2012-07-24T20:08:12.587 に答える