javaのsocket通信で20KB以上の文字列を

このQ&Aのポイント
  • javaのsocket通信で20KB以上の文字列を送信する際に通信が途中で止まってしまう問題が発生しています。
  • 文字列を分割して送るなどの対策は行っていますが、根本的な解決には至っていません。
  • InputStreamReaderとBufferedReaderを使用して問題を解決する方法について教えてください。
回答を見る
  • ベストアンサー

javaのsocket通信で20KB以上の文字列を

javaのsocketについての質問です。サーバーとandroid端末で文字列のやりとりしています。 文字列は長いので、圧縮をかけ、android端末側で解凍を行っています。 そこで問題がおきました。文字データ量(20KB)が大きくなると、通信が完了せずに途中で止まってしまうのです。そこで文字列を分割(1KB毎)して送るなどを行い、しのいでおりましたが根本的の解決にはいたっていません。 InputStreamReader 、 BuffererdReader あたりを考えればいいと思うのですが、いまいち組み方がよくわからない状態です。 どなたか教えていただけないでしょうか? ============================= サーバー(PC側ソースコード)DataCompression は文字列を送って圧縮をかける独自のクラスです。 public class DataExchange extends Thread{ /* android端末とデータのやり取りをする */ private boolean DEBUG_FLAG = true; // private boolean DEBUG_FLAG = false; private InputStream is; private OutputStream os; private String sendStr; private String receiveStr; public DataExchange(InputStream is, OutputStream os, String sendStr) { this.is = is; this.os = os; this.sendStr = sendStr; } public void run() { //送信データ圧縮 DataCompression dc = new DataCompression(); byte[] sendByte = dc.getDataCompression(sendStr); //データ送信 try { os.write(sendByte); os.flush(); } catch (IOException e) { e.printStackTrace(); } if (DEBUG_FLAG) { System.out.println(os + " データ送信完了 = " + sendStr); } //データ受け取り byte[] buffer = new byte[1024]; try { int size = 0; while (size <= 0) { size = is.read(buffer); } receiveStr = new String(buffer, 0,size, "UTF8"); } catch (IOException e) { e.printStackTrace(); } if (DEBUG_FLAG) { System.out.println(is + " データ受信完了 = " + receiveStr); } } public String getReceiveStr() { return receiveStr; } } ========================================= android端末側ソースコード public class DataExchange extends Thread{ /* android端末とデータのやり取りをする */ private InputStream is; private OutputStream os; private String sendStr; private String receiveStr; public DataExchange(InputStream is, OutputStream os, String sendStr) { this.is = is; this.os = os; this.sendStr = sendStr; } public void run() { //データ受け取り byte[] buffer = new byte[4096]; try { int size = 0; while (size <= 0) { size = is.read(buffer); } receiveStr = new String(buffer, 0,size, "UTF8"); } catch (IOException e) { e.printStackTrace(); } /* 解凍 */ Inflater decompresser = new Inflater(); decompresser.setInput(buffer); int count; ByteArrayOutputStream decompos = new ByteArrayOutputStream(); while (!decompresser.finished()) { try { count = decompresser.inflate(buffer); decompos.write(buffer, 0, count); } catch (DataFormatException e) { e.printStackTrace(); } } receiveStr = decompos.toString(); System.out.println("データ受信完了 = " + receiveStr); //データ送信 try { byte[] sendByte = sendStr.getBytes("UTF8"); os.write(sendByte); os.flush(); } catch (IOException e) { e.printStackTrace(); } System.out.println("データ送信完了 = " + sendStr); } public String getReceiveStr() { return receiveStr; } }

  • Java
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • _kappe_
  • ベストアンサー率68% (1522/2216)
回答No.1

明らかにおかしい部分が複数あります。 //データ受け取り byte[] buffer = new byte[4096]; try { int size = 0; while (size <= 0) { ★1 size = is.read(buffer); } receiveStr = new String(buffer, 0,size, "UTF8"); ★2 } catch (IOException e) { e.printStackTrace(); } ★1 このループ条件だと、 ・is.read(buffer)でデータを読み込めた場合(最大4096バイト)にはすぐにwhileループ脱出 ・データを読み込めなかった場合(ストリームの終わりに達していた場合)は、無駄なis.read()を永遠に繰り返す という動作になってしまいます。 これでは、サーバーが4096バイトを超えるデータを送ってきた場合、4097バイト目以降を端末側が読むことはありません。 サーバー側のデータ受け取りコードにも同じ問題があります。 ★2 bufferに入っているのは圧縮がかかったデータのはずです。圧縮されたままのデータを使ってnew String()を実行したら、得られるのは文字化けしたデータです。

nakisan2011_12
質問者

お礼

ありがとうございます、こちらのコードを参考にしてもう一度組んでみたいと思います。

関連するQ&A

  • java でソケット通信をするとき

    javaでソケット通信をするとき、 //データ受け取り byte[] buffer = new byte[2048]; try { int size = 0; while (size <= 0) { size = is.read(buffer); } receiveStr = new String(buffer, 0,size, "UTF8"); } catch (IOException e) { e.printStackTrace(); } のようにしていますが、これだと文字数にして一度におくれる容量はどのくらいでしょうか? また、それらを増やすにはどうしたらいいでしょうか?

    • ベストアンサー
    • Java
  • TCP/IP通信について

    現在、以下のようにTCP/IP通信のプログラミングを行っており、 サーバ/クライアント別々に4byteのデータ送信を10msec毎に10秒間行っております。 現在、WimdowsVista-Windows7間で各々をサーバ/クライアントとして順に起動し、 相互に4byte送信しているハズが、倍の8byteや12byteとデータが連なって送信されている 事象が発生してます。 OutputStreamではwrite後にflushを行っているので、flush契機でメモリ上に蓄えられた 送信用バッファが送信されるイメージでおりますが、4byteで送信できていないように見えます。 上記について、解決方法をご存じであればご教授お願い致します。   <Server.java> ===== public class Server {  public static ServerSocket ss = null;  public static Socket soc = null;  private static InputStream is = null;  private static OutputStream os = null;  public static void main(String[] args) {      try {    // サーバソケット生成    ss = new ServerSocket(5000);    soc = ss.accept();    is = soc.getInputStream();    os = soc.getOutputStream();    Thread rcvTh = new ServerRcvThread(is);    rcvTh.start();    Thread sndTh = new ServerSndThread(os);    sndTh.start();    // 10秒スリープ    try{     Thread.sleep(10000);    } catch ( Exception e){     e.printStackTrace();    }    // スレッド停止    rcvTh.stop();    sndTh.stop();   } catch (IOException e) {    e.printStackTrace();   } finally{    try {     is.close();     os.close();     soc.close();     ss.close();    } catch (IOException e) {     e.printStackTrace();    }      }  } } class ServerSndThread extends Thread{  private static OutputStream ous = null;  ServerSndThread( OutputStream os ){   this.ous = os;  }  public void run(){   byte sndData[] = new byte[4];   sndData[0] = 0x01;   sndData[1] = 0x02;   sndData[2] = 0x03;   sndData[3] = 0x04;   try {    while(true){     // データ書込み     ous.write(sndData);     ous.flush();     System.out.println("データ送信");     // 0.01秒スリープ     try{      Thread.sleep(10);     } catch ( Exception e){      e.printStackTrace();     }    }   } catch (IOException e) {    e.printStackTrace();   }  } } class ServerRcvThread extends Thread{  private static InputStream ins = null;  ServerRcvThread( InputStream os ){   this.ins = os;  }    public void run(){   byte rcvData[] = new byte[16];   int size = 0;   try {    while(true){     // データ読込み     size = ins.read(rcvData);     System.out.println("size:"+size+"byte");    }   } catch (IOException e) {    e.printStackTrace();   }  } } =====     <Client.java> ===== public class Client {  private static Socket soc = null;  private static OutputStream os = null;  private static InputStream is = null;  public static void main(String[] args) {   try {    // ソケット生成    soc = new Socket("192.168.3.3", 5000);    is = soc.getInputStream();    os = soc.getOutputStream();    Thread rcvTh = new ClientRcvThread(is);    rcvTh.start();    Thread sndTh = new ClientSndThread(os);    sndTh.start();    // 10秒スリープ    try{     Thread.sleep(10000);    } catch ( Exception e){     e.printStackTrace();    }    // スレッド停止    rcvTh.stop();    sndTh.stop();   } catch (IOException e) {    e.printStackTrace();   } finally{    try {     is.close();     os.close();     soc.close();    } catch (IOException e) {     e.printStackTrace();    }      }     } } class ClientSndThread extends Thread{  private static OutputStream ous = null;  ClientSndThread( OutputStream os ){   this.ous = os;  }    public void run(){   byte sndData[] = new byte[4];   sndData[0] = 0x04;   sndData[1] = 0x03;   sndData[2] = 0x02;   sndData[3] = 0x01;   try {    while(true){     // データ書込み     ous.write(sndData);     ous.flush();     System.out.println("データ送信");     // 0.01秒スリープ     try{      Thread.sleep(10);     } catch ( Exception e){      e.printStackTrace();     }    }   } catch (IOException e) {    e.printStackTrace();   }  } } class ClientRcvThread extends Thread{  private static InputStream ins = null;  ClientRcvThread( InputStream os ){   this.ins = os;  }    public void run(){   byte rcvData[] = new byte[16];   int size = 0;   try {    while(true){     // データ読込み     size = ins.read(rcvData);     System.out.println("size:"+size+"byte");    }   } catch (IOException e) {    e.printStackTrace();   }  } } =====

    • ベストアンサー
    • Java
  • Return で文字列が返せない、、

    このような関数を作って、mainの関数に渡したいのですが、文法がダメだとコンパイラに怒られます。 private String test(){ try{ FileOutputStream fos=openFileOutput("sample.txt", MODE_PRIVATE); String text="サンプルテキストです"; fos.write(text.getBytes()); fos.close(); }catch(FileNotFoundException e){ }catch(IOException e){ } try{ FileInputStream fis=openFileInput("sample.txt"); byte buffer[]=new byte[100]; fis.read(buffer); String str = new String(buffer).trim(); fis.close(); return str; }catch(FileNotFoundException e){ }catch(IOException e){ } }なぜ返せないのでしょうか。

    • ベストアンサー
    • Java
  • javaのudp通信について

    javaのudp通信を使用して簡単なチャットプログラムを作っています。サーバーなどは使用しないものです。 送信、受信それぞれのプログラムはできました。送信は送信を繰り返し、受信も受信を繰り返すものです。それをひとつにしたいと考えています。 送信プログラムの詳細はhttp://oshiete1.goo.ne.jp/qa3743572.htmlです。 受信プログラムは下記です。 ご指導お願いします。 ******************************** import java.net.*; public class reciverTest { DatagramPacket packet1; private DatagramSocket socket1; private int port = 19800; public reciverTest() throws Exception { this.socket1 = new DatagramSocket(this.port); } public String receive() throws Exception { byte buffer[] = new byte[256]; int i; packet1 = new DatagramPacket(buffer, buffer.length); this.socket1.receive(packet1); // blocking for (i = 0; i < buffer.length; i++) { if (buffer[i] == '\0') { break; } } String msg = new String(packet1.getData(), 0, i); return msg; } public void close() throws Exception { socket1.close(); } public static void main(String[] args) { reciverTest receiver1; System.out.println("Waiting ..."); try { receiver1 = new reciverTest(); while(true) { String msg = receiver1.receive(); System.out.println("受信したデータ⇒『" + msg +"』を受信しました。"); receiver1.close(); } } catch (Exception ex) { System.err.println("Error: " + ex.getMessage()); } } }

    • ベストアンサー
    • Java
  • URLで指定したページのデータを読むには?

    URLをしていしてデータを読み込みたいのですが”java.net.ConnectException: Connection timed out”となってしまいます。なぜでしょうか。 import java.io.*; import java.net.*; /** * ウェブ上のデータを取得するサンプル * */ public class GetFileFromWeb { public static void main(String[] args){ URL url = null; //HttpURLConnection con = null; try{ //URLの指定 url = new URL("http://www.****"); //入力ストリームを取得する InputStream is = url.openStream(); //URLからデータを読み取り、表示する。 byte[] data = new byte[1024]; int i; while((i=is.read(data))!=-1){ System.out.write(data, 0, i); } }catch(MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

    • ベストアンサー
    • Java
  • Socket通信でのデータの受け渡し

    サーバーが受けたデータを、クライアントに返す プログラムですが、 サーバーは、クライアントからのデータを、 while(true){ BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream())); str=br.readLine(); if(str!=null){ PrintWriter pr=new PrintWriter(s.getOutputStream()); pr.println(str); pr.flush(); }}で、返すようにしています。 クライアントも大体同じです(PrintWriterは、 Buttonを押した時に、取得しています)。 考え方としては、inputstreamは、無限ループで、 取得し、outputstreamは、必要におうじて、取得し データを送っています。 しかし、これだと、一度データを送ると、次から データの受け渡しが出来なくなります。 socketか、inputstreamかoutputstreamのどれかが、 閉じるか、使えなくなるのだと思いますが、 いつもここで、悩んでいます。 (また、無限ループで、BufferedReaderオブジェクト をつくり続けるというのも、ちょっと不安)。 どこに問題があるのか、分かる人教えてください。 お願いします。

    • ベストアンサー
    • Java
  • InputStream.read()でタイムアウトの処理をしたい。

    InputStream.read()でタイムアウトの処理をしたい。 現在自分は、InputStreamに入力されたデータをOutputStreamに移したいとかんがえているのですが、途中でreadメソッドが固まってしまいうまくいきません。 ソースで説明させていただきますと、 public static int copy(InputStream input,OutputStream output)throws IOException { byte[] buffer = new byte[1024 * 4]; int count = 0; int n = 0; while (0 < (n = input.read(buffer))) //ここで固まる { output.write(buffer, 0, n); count += n; System.out.println("available = " + input.available()); System.out.println(count + " byte = " + n); } return count; } このようなコピーするメソッドを書いたのですが、何度かループした後readメソッドで固まってしまいます。また、availableは常に0を返しております。 おそらくストリームの終わりが検出できないため、このような状態になっていると推測されるのですが、プログラムの性質上、InputStreamに入ってくるデータを変更することはできません。 なのでこの問題を解決するべく、ある程度の時間readメソッドがブロックされたら、breakするというような処理を書きたいのですが、どのようにすればよいでしょうか?

    • ベストアンサー
    • Java
  • バイナリファイルでOutOfMemoryエラー

    お世話になります。 ブラウザ画面からファイルをアップロードし、そのバイナリデータを返すメソッドを作成したのですが、約50MB以上のファイルを使用するとOutOfMemoryエラーとなりJava heap spaceが足りないといわれてしまいます。ヒープサイズをあげればエラーはしなくなるとはおもいますが、根本的な解決にはならないと思います。 public byte[] upload(FormFile ff) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = ff.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); byte[] byteData; try { int data = 0; byte[] buffer = new byte[1024]; while ((data = bis.read(buffer) != -1) { baos.write(buffer, 0, data); } byteData = baos.toByteArray(); } catch (IOException e) { throw e; } finally { if (null != bis) { bis.close(); } } return byteData; } 以上のようなメソッドなのですが、おかしい点はありますでしょうか。 指摘していただけると助かります。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • java通信について

    アプレットビューアは 通信成功できますが HTMLから実行すると失敗します so = new Socket( "localhost", 80 ); この部分が失敗してるようです なぜ起こるんでしょうか ? 解決方法を教えてください。 //html <html><body> <applet code = "a.class" width = "370" height ="530"></applet> </body></html>   //<applet code = "a.class" width="400" height = "200"></applet> import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; public class a extends java.applet.Applet implements ActionListener{ TextField tf; Button b; TextArea t; Panel p, p1; String str = "http://localhost/cgi-bin/a.cgi"; public void init(){ tf = new TextField( 32 ); b = new Button( "Post" ); t = new TextArea( 20, 48 ); b.addActionListener( this ); p = new Panel(); p.add( new Label( "String" ) ); p.add( tf ); p.add( b ); p1 = new Panel(); p1.add( t ); add( p ); add( p1 ); } public void actionPerformed( ActionEvent e ){ String str; if( e.getSource() == b ){ t.setText( sen( tf.getText() ) ); } } private String sen( String a ){   Socket so = null; InputStreamReader in = null; OutputStream os = null; String str1 = new String(); try { t.setText( "aa" ); so = new Socket( "localhost", 80 ); t.setText( "bb" ); in = new InputStreamReader( so.getInputStream() ); os = so.getOutputStream(); }catch( Exception e ){ return "Error!"; } String H = "POST " + str + " HTTP/1.0\n"; H += "Content-Length:" + String.valueOf( a.length() ) + "\n\n"; String st = new String( H + a ); try{ os.write( st.getBytes() ); }catch( Exception e ){ return "Error!"; } str1 = "Send:\n" + st; boolean bo = true; StringBuffer sb = new StringBuffer(); int s; while( bo ){ try{ s = in.read();   if( s == -1 ) bo = false; else sb.append( (char)s ); }catch( Exception e ){ bo = false; } } str1 += "\nResv:\n" + sb.toString(); return str1; } }

    • ベストアンサー
    • Java
  • javaアプレットとPHPの通信

    タイトルの通りなのですが、 javaアプレットで出た結果(Stringや数値)を phpに送信する方法が知りたいです。 他のサイトを調べていたら、 下の様なプログラムがありました。 private String send(String stArg) { try { //送信先URL URL url = new URL(getCodeBase(), "sample.php"); //ネットワーク接続 URLConnection urlCon = url.openConnection(); urlCon.setDoOutput(true); urlCon.setDoInput(true); urlCon.setAllowUserInteraction(false); //送信処理 PrintWriter writer = new PrintWriter(urlCon.getOutputStream()); writer.print(stArg); writer.close(); } catch (Exception e) //エラー処理 { e.printStackTrace(); } return "error"; } } これはString stArgをsample.phpに送る処理だと 書いてあったのですが、 php側でどういった様に受信すれば良いのかがわかりません。。。 自分のイメージとしては、アプレットから送信したデータ(stArg)を php上でPOST[$stArg]と言った形で受信したいです。 私の考え方自体がおかしいかもしれないですが、 何か良い方法、または良いサイトを知っていたら お教えいただきたいです。

専門家に質問してみよう