2012-01-16 5 views
0

私はJavaチャットサーバー&クライアントを持っていますが、うまくいきます。私は別々にクライアントファイル転送プログラムにサーバーを作った、それは正常に動作しています。しかし、私がチャットにファイル転送を統合しようとすると、ファイルが転送されていますが、その間、チャットプログラムはちょうどフリーズし、チャットボックスに何かを入力することさえできず、転送が終わると物事は正常になります。チャットやファイル転送が並んで行われているように、それを正常にする方法、他に影響を受けるものはありませんか?ファイル転送中にjava - chatプログラムがハングしますか?

私のファイル転送にはサーバーとクライアントの両方でループがありますが、whileループのためこのことを知りたいのですが、ファイル転送のサーバーとクライアントコードの両方にスレッドを作成する必要があります。 私のチャットシステムは、サーバー上でユーザーが接続するようなものです。ユーザーからの読み取りのために、そのユーザーのサーバー上でスレッドが開始され、ユーザーからのメッセージがユーザーに送信されます。 クライアントでは、スレッドはサーバーからの読み取り用です。ユーザーがメッセージを入力すると、サーバーに送信され、サーバーに接続されたすべてのユーザーにメッセージが返されます。

私はちょうど私の友人とインターネットでこれをテストしたので、問題はクライアント側であると思います。私は両方のチャットのためにサーバーでした&ファイル転送、私のチャットボックスはうまくいきました。チャットクライアントfreezd時間のファイル転送が行われました。

おかげで、 任意の助けが理解されるWUD ..私はこれを引き起こしているコードのどの部分かわからないので、私は、すぐに誰かがそれを要求するよう、コードでこれを更新します。

[EDIT - クライアント上のファイルの転送]

public class FileClient{ 


JFrame jfr; 
JTextField Jtf = new JTextField(4); 
public static void main (String [] args) { 

// new FileClient().go(); 

} 

public void go(String ip){ 
    try{ 
    JFrame jfr = new JFrame("File Transfer"); 
      JPanel panel = new JPanel(); 
    JLabel jl = new JLabel("Progress:"); 
    jfr.getContentPane().add(BorderLayout.CENTER,panel); 
    panel.add(jl); 
    panel.add(Jtf); 
    Jtf.setEditable(false); 
    jfr.setSize(200,70); 
    jfr.setVisible(true); 
    jfr.setDefaultCloseOperation(jfr.EXIT_ON_CLOSE); 
}catch(Exception e){e.printStackTrace();} 
long start = System.currentTimeMillis(); 
    int read; 
    int totalRead = 0; 
    try{ 
    Socket sock = new Socket(ip,4243); 
    System.out.println("Connecting..."); 
    InputStream is = sock.getInputStream(); 
    BufferedInputStream bis = new BufferedInputStream(new ProgressMonitorInputStream(jfr,"reading",is)); 

    byte [] mybytearray = new byte [512]; 
    int buff =1024; 
    byte[] nameByte = new byte [50]; 
    byte[] nameByteSize = new byte [2]; 
    byte[] Size = new byte [10]; 
    byte[] SizeSize =new byte [1]; 

    int num = is.read(nameByte,0,50); 
    int nameSize = is.read(nameByteSize,0,2); 
    int sz = is.read(Size,0,10); 
    int yy = is.read(SizeSize,0,1); 
    float w; 

    String Size1 = RemoveNameStuffing(new String(Size),new String(SizeSize)); 
    int tt = Integer.parseInt(Size1); 
    System.out.println("tt"+tt); 
    name"+new String(nameByte)); 
    String name = RemoveNameStuffing(new String(nameByte),new String(nameByteSize)); 
    File f1=new File(name); 

    FileOutputStream fos = new FileOutputStream(f1); 
    BufferedOutputStream bos = new BufferedOutputStream(fos); 

    while ((read = bis.read(mybytearray,0,mybytearray.length)) != -1) { 
      bos.write(mybytearray, 0 , read); 
      totalRead += read; 
      w=((float)totalRead/tt)*100; 
      System.out.println("progress:"+w+"%"); 
      Jtf.setText(w+"%"); 
    } 


    bos.flush(); 
    long end = System.currentTimeMillis(); 
    System.out.println(end-start); 
    bos.close(); 
    sock.close(); 
    }catch(IOException e){e.printStackTrace();} 
} 

public static String RemoveNameStuffing(String s, String n){ 

    s=s.substring(0,Integer.parseInt(n)); 
    System.out.println("s:"+s); 

    return s; 

} 

}

[EDIT - これは私がチャットクライアントにファイル転送コードを呼び出すAM HOW IS]

public class AcceptFileButtonListener implements ActionListener { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // TODO Auto-generated method stub 
     FileCl.go(JTip.getText()); 
    } 

} 

[編集 - ファイル転送サーバーコード - バッファーサイズ512]

//Waiting for connection 
//Sending name in bytes 
//While{ 
    send files as bytes 
    } 

public void actionPerformed(ActionEvent e) { 

     FileSv.go(); 

    } 

と私のサーバーでも、すぐにFTサーバーがない場合であっても、私は、ボタンを押すとフリーズ[ABOVE(FTサーバ)CODEが呼び出されたチャットサーバ]接続しても(私はこの援助と思います)。

私はチャットサーバーとクライアントを持っていて、どちらも相互に読み込むスレッドを持っています。私はファイル転送サーバーとクライアントを既存のチャットサーバーとチャットクライアントに統合しようとしました。 最初にユーザーがチャットサーバーに接続すると、チャットサーバーのスレッドが開始されます。そのユーザーにファイルを送信するために、私はサーバー上で1つのボタン(ファイル送信)を作成し、クライアント上では1つ(ファイルを受け入れる)を作成し、サーバー上で「ファイル送信」をクリックすると、ファイル転送サーバーコードが実行され、私が完全にチャットしているユーザーが「ファイルを受け入れる」をクリックすると、Severは別のポートで接続を待つ(私のチャットサーバーがフリーズし、現在は応答しないtextFieldを持つ)。ファイル転送クライアントコードが実行される。 FTサーバはバイトを送信し始め、FTクライアントはそれをrcvsします。サーバーとクライアントの両方のチャットウィンドウは、転送が行われたときに応答しなくなり、転送中にクライアント側のチャットボックスから送信したものは転送後に更新されます。 これは混乱を解消するためです。これが助けにならなくても、私は全体のコード(大きすぎます)をアップロードします

+1

チャットとファイル転送(クライアントまたはサーバー上)の処理と同じスレッドですか? –

+0

あなたのコードを見ることなく、我々はちょうど推測するだろう。 –

+2

チャットと同じスレッドでファイル転送を実行しているようです。複数の同時転送を処理する場合は、ファイル転送用に別のスレッド、またはファイル転送ごとに1つのスレッドが必要になります。 – vaughandroid

答えて

1

私のコメントを拡張するには、[OK]を - あなたはwhen clicked on a button on the clientchat window, FileTransferClient side is initiated, which works on while loop to read byte from server.

を言うあなたは、Swingイベントスレッドでファイル転送のコードを実行していますか?そうであれば、それをRunnableオブジェクトの中にラップし、whileループの反復間の処理時間を短縮し、SwingUtilitiesを使用して呼び出すようにする必要があります。

ボタンを押して別のスレッドを開始してファイルを転送する場合は、送信ループのループ間で処理時間を引き上げる必要があります。また、チャット処理に処理時間を必要としません。スレッド。

編集:次の操作を実行するために、あなたのアクションリスナーの呼び出しを修正:

@Override 
public void actionPerformed(ActionEvent e) { 
    // TODO Auto-generated method stub 
    SwingUtilities.invokeLater(
     new Runnable() { 
     public void run() { 
      FileCl.go(JTip.getText()); 
     } 
     } 
    ); 
} 

これは何は、Swingイベントスレッドへの外部新しいスレッドの中にCPUと、ファイルのダウンロードのIO集中的な処理を移動しています。

+0

いいえ、私はファイル転送コードでどんな種類のスレッディングシステムを使用してもかまいません。私はそれを別に作った、クライアント/クライアント上のWHILEループを使って/ rcvバイトを送る。 – Nikhar

+0

そして、あなたはボタン上のActionListenerの内側からgo()を呼び出していると思います。 – mcfinnigan

+0

あなたは正しいです、私はちょうどコードを含んでいます。 – Nikhar

3

非同期操作をしたいときに同期操作を使用するという告白があります。

私の推測では、あなたのアプリケーション用のスレッドは1つ、またはリモート通信用のスレッドは1つあります。あなたは、非同期通信にjavaのnioクラスを使用していない可能性があります。

nioクラスを調べたり、現在のファイル送信コードとファイル受信コードを別のスレッドで実行したりできます。

前者の実装は、適切なnioチュートリアル(ここではoneです)にあります。

後者の共通の実装は、メッセージ/ファイルを送信するためのコマンドパターンと、プロデューサ/コンシューマスレッドを持つコマンドキューを使用することです。あなたはCommandクラスとして "Runnable"インターフェースを扱うことができます。

public class MessageCommand implements Runnable { 
    private String message; 
    public MessageCommand(String message) { this.message = message; } 
    public void run() { /* code to send the message goes here */ } 
} 

public class FileCommand implements Runnable { 
    private File file; /* or byte[] or whatever */ 
    public MessageCommand(File file) { this.file = file; } 
    public void run() { /* code to send the file goes here */ } 
} 

は、その後、これらのタイプのオブジェクトを取る可能性がQueue<Runnable>、ConcurrentLinkedQueueのいくつかの種類を持っている、とプロデューサ/コンシューマを使用します。コードの受信側で別のスレッドもスピンオフする必要があることに注意してください。そうしないと、非同期で送信することができますが、受信中はブロックされます(メッセージでは問題ありませんが、ファイルには迷惑です)。

+0

OK、私は完全に新人ですが、私はクライアント側のスレッドをサーバーから受け取り、サーバーからソケットからチャットメッセージを読み取るスレッドを実行しているサーバーからファイルを受け入れるようにすれば、違いが生じると思いますか?つまり、私は今、サーバー上で、クライアントからのチャットメッセージを読むためのスレッドを1つと、クライアントに(別のポート上の)バイトを送信するためのスレッドを1つ持っています。 2つのスレッド、1はサーバーから、1はバイトを受信するために使用されますか? – Nikhar

+0

私はおそらくファイルとファイルをブロックし、チャットとチャット(とにかく、チャットを注文したいと思い、1つのスレッドは、チャットメッセージを送信するコードを簡単にする)が良いと思う。私はあなたがコードを投稿する前に実際に私の答えを始めたので、私はあなたのプログラムの構造について私が上記を書いたときには何も知らなかった。私の答えの特異性の欠如はそれを反映しています。 – ccoakley

+0

はい、私はそれを感じましたが、私はニオを勉強します。あなたは何が間違っていると推測していますか? – Nikhar

関連する問題