- PR -

画像ファイルのソケット通信

投稿者投稿内容
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2005-02-09 14:39
そのコードだと、サーバもクライアントもソケットに対してwriteするだけですね。
お互いに、相手が送ってきたデータを受け取らずに自分からデータを送ろうとするだけなので
まともに動くはずありません。

もう一度、ご自分が何をやりたいのか、落ち着いて考え直してください。
ダウンロードですか? アップロードですか?
いずれにしても、一方がソケットにwriteするなら、もう一方でソケットをreadするはずです。
未記入じゃけんど
ベテラン
会議室デビュー日: 2004/11/09
投稿数: 65
お住まい・勤務地: Osaka City
投稿日時: 2005-02-09 16:44
すいません、貼るソースをまちがえていました。
実際は下記のような感じです。
バイナリファイルを受信した後、クライアントに画像を保存しますが、
画像ファイルを見ることができません。
ファイルが壊れているのでしょうか?

***サーバー側***
ServerSocket serversock = new ServerSocket(5555);
Socket sock = null;
sock = serversock.accept();

BufferedReader sockin = new BufferedReader(new InputStreamReader(sock.getInputStream()));
OutputStream sockout = sock.getOutputStream();

FileInputStream tmpFI= new FileInputStream("image3.jpg");
ByteArrayOutputStream receivedBuffer = new ByteArrayOutputStream();
byte b[] = new byte[1];
int len =-1;
while((len=tmpFI.read(b,0,b.length))!=-1){
receivedBuffer.write(b,0,len);
}

receivedBuffer.flush();
byte buf2[] = receivedBuffer.toByteArray();
sockout.write(buf2, 0, buf2.length);
System.out.println(buf2.length);
sockout.write(buf2.length);
sockout.flush();

receivedBuffer.close();
// ソケットのクローズ
sockout.close();
sockin.close();
sock.close();

***クライアント側***
Socket sock = null;
InputStream in = null;
DataInputStream dis = null;
int id;
String name;
Button mybtn1,mybtn2;
byte[] ciphertext;

// ソケット通信で文字列を受信
try {
// サーバーのポート番号
sock = new Socket("192.168.0.82",5555);
// サーバーとの通信用入力ストリーム
in = sock.getInputStream();
dis = new DataInputStream(in);
// サーバからのデータを受信
// 画像ファイル読込ロジック実装予定
int length = dis.readInt();
System.out.println(length);
length = 29134;
BufferedInputStream rsTgsBuf = new BufferedInputStream(dis);
ByteArrayOutputStream Bout = new ByteArrayOutputStream();

for (int i = 0; i < length; i++) {
Bout.write((byte)rsTgsBuf.read());
}
ciphertext = Bout.toByteArray();

// 保存するファイルストリーム
FileOutputStream tempFO = new FileOutputStream("image000.jpg");
//tempFO.write(ciphertext,0,ciphertext.length);
// 1バイトずつ書き込み
for (int i = 0; i < length; i++) {
tempFO.write(ciphertext,0,1);
}
tempFO.flush();
tempFO.close();

rsTgsBuf.close();
dis.close();
in.close();
sock.close();


です。
金床
会議室デビュー日: 2005/02/03
投稿数: 9
投稿日時: 2005-02-09 16:54
バイナリデータの読み書きにはReader・Writerは使わないのが普通かもしれないです。
バッファリングしたいならBufferedInputStreamなどを使うのが良いでしょう。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2005-02-09 17:56
致命的な問題点は2箇所。
(1) クライアント側は、ファイルの内容に先立ってファイルサイズが送られてくることを
想定しているようですが、サーバ側にはその処理がありません。

(2) たぶん、(1)のクライアント側でファイルサイズを受け取る処理が上手く動作しなかった
(サーバはファイルサイズを送らないのだから動作するはずもない)
のをリカバーするためでしょうが、ファイルサイズを29134と決め打ちにしています。

他に気になる個所は、

(3) サーバ/クライアントどちらも、データ全体をいったんメモリー上に読み込むように
なっていますが、この方式はファイルサイズが大きいときに困るので、やめた方が良い。

(4) サーバ/クライアントどちらも、データを1バイトずつ読み書きするようになっていますが、
これは効率を損ねるので、適切なブロックサイズで扱うようにしたほうが良い。
いっきゅう
大ベテラン
会議室デビュー日: 2004/04/04
投稿数: 153
お住まい・勤務地: 兵庫
投稿日時: 2005-02-09 19:09
金床さん、coasmさんの指摘をまとめると
いただけない部分もあるが動きはこんな感じかな?

コード:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class Test implements Runnable {

    String S_PATH ="e:\\image.png";
    String C_PATH ="e:\\out.png";
    
    public void run() {
        server();
    }
    public void server() {
        try {
            ServerSocket ss = new ServerSocket(9999);
            Socket soc =ss.accept();
            BufferedOutputStream out = new BufferedOutputStream(soc.getOutputStream());
            FileInputStream in = new FileInputStream(S_PATH);
            byte[] buf = new byte[1024];
            int len = 0;
            while( (len=in.read(buf)) != -1 ) {
                out.write(buf,0,len);
            }
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void client() {
        try {
            
            Socket soc = new Socket("localhost",9999);

            BufferedInputStream in = new BufferedInputStream(soc.getInputStream());
            FileOutputStream out = new FileOutputStream(C_PATH);
            byte[] buf = new byte[1024];
            int len = 0;
            while( (len=in.read(buf)) != -1 ) {
                out.write(buf,0,len);
            }
            out.close();
            in.close();

            JFrame frame = new JFrame(){
                BufferedImage bi = ImageIO.read(new java.io.File(C_PATH));
                public void paint(Graphics g) {
                    g.drawImage(bi,0,0,bi.getWidth(),bi.getHeight(),null);
                }
            };
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(new Dimension(800, 600));
            frame.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main ( String args[]) {
        Thread kick = new Thread(new Test(),"server");
        kick.start();
        
        new Test().client();
    }
}

未記入じゃけんど
ベテラン
会議室デビュー日: 2004/11/09
投稿数: 65
お住まい・勤務地: Osaka City
投稿日時: 2005-02-10 11:23
みなさん本当にありがとうございます。

おかげさまで、ソケット通信で画像を受信する処理ができました。
本当にありがとうございます。
未記入じゃけんど
ベテラン
会議室デビュー日: 2004/11/09
投稿数: 65
お住まい・勤務地: Osaka City
投稿日時: 2005-02-10 11:39
追加で質問ですが

ソケットクライアントにて受信した、バイナリに変換された画像データを
保存せずに、アプレットで表示させてやることは可能でしょうか?
パテ太
ベテラン
会議室デビュー日: 2004/08/16
投稿数: 64
お住まい・勤務地: 千葉・東京
投稿日時: 2005-02-10 11:56
パテ太です。
質問に質問を返して申し訳ないのですが
未記入さんのなさりたいことは
「Web サーバ上にあるグラフィックデータを
 ダウンロードしてアプレットに表示したい」
ということですか?

スキルアップ/キャリアアップ(JOB@IT)