0

こんにちは、クライアント用とサーバー用のコードを書きましたが、クリント 1 とクリント 2 の間でメッセージを配信したいのですが、サーバー側でこれを行うことができません。名前と ID の配列を作成し、クライアントからメッセージを送信した後サーバーがメッセージを配信する場所または名前を選択できます。これを書くのを手伝ってください。これがクリント側です

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;


public class client {

    public static void main(String[] args) {
        Socket socket = null; 
        try {
            socket = new Socket("127.0.0.1", 7777);
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            BufferedReader readerFromCommandLine = new BufferedReader(new InputStreamReader(System.in));
            PrintWriter writer = new PrintWriter(socket.getOutputStream());

            while(true) {                               
                System.out.println("Say something:");
                String userInput = readerFromCommandLine.readLine();
                writer.println(userInput);
                writer.flush();

                String input = reader.readLine();               

                System.out.println("Got from server: "+input);

                if (userInput.equalsIgnoreCase("bye")) {
                    break;
                }
            }
        }
        catch(Exception e) {
            System.err.println(e);
            e.printStackTrace();
        }
        finally {
            if (socket != null) {               
                try {
                    socket.close();
                } 
                catch (Exception e) {
                    System.err.println(e);
                    e.printStackTrace();
                }               
            }
        }
    }

}

だから今、私のコードはこのように見えますか?私はまだ1つのクライアントからクライアント2に送信できないため

import java.awt.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;


public class server {

    public static void main(String[] args) {
        ArrayList<Channel> my_clients = new ArrayList<Channel>(); 
        ServerSocket ss = null;

        try {
            ss = new ServerSocket(7777);            

            while (true) {
                //wait for a new client call - once got it, get the socket for
                //that channel

                System.out.println("Waiting for an incoming call");
                Socket client = ss.accept();
                Channel my_new_client = new Channel(client); 
                my_clients.add(my_new_client); 
                my_new_client.start();
                //once the call has started read the client data
                for(Channel my_client : my_clients) { 
                    if(my_client.getName() == "Me") { 
                        //my_client.writer("HELLO!"); 

                    }
                }
                //System.out.println("Accepted a new call");                                
                //new Channel(client).start();

            }
        }
        catch(Exception e) {
            System.err.println(e);
            e.printStackTrace();
        }
        finally {
            if (ss != null) {
                try {
                    ss.close();
                }
                catch(Exception e) {
                    System.err.println(e);
                    e.printStackTrace();
                }
            }
        }

    }



     public static class Channel extends Thread {

         private static int clientIndex = 0;
         private int index;

        private Socket socket = null;

        public Channel(Socket socket) {
            clientIndex++;
            index = clientIndex;
            this.socket = socket;
        }

        @Override
        public void run() {

            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter writer = new PrintWriter(socket.getOutputStream());

                while (true) {  

                    String input = reader.readLine();                   
                    System.out.println("Got from client "+index+": "+input);

                    //bye bye
                    if (input.equalsIgnoreCase("bye")) {
                        break;
                    }
                    writer.println("Gotcha");
                    writer.flush();                         
                }
            }
            catch(Exception e) {
                System.err.println(e);
                e.printStackTrace();
            }
            finally {
                if (socket != null) {
                    try {
                        socket.close();
                    }
                    catch(Exception e) {
                        System.err.println(e);
                        e.printStackTrace();
                    }
                }
            }
        }

    }

}
4

2 に答える 2

0

文字列 userInput = readerFromCommandLine.readLine();

ここでは BufferedReader.readLine() が問題です。入力が受信されるまでスレッドをブロックします。これは、通信が一度に一方向にしか進行できず、両方のクライアントが待機している場合に完全にブロックされる可能性があることを意味します。

DataFetcher でこの問題を解決できます。別のスレッドで聞くために使用できます

http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/

于 2012-05-18T14:35:15.570 に答える
0

あなたはそこまでの道のりです。

クライアントからの各接続がスレッドを開くスレッドサーバーを作成しました。その後、このスレッドはループしてメッセージを待ちます。

これらのスレッドは、クライアントを独自のオブジェクト/プロパティとストリームに接続して読み書きするものと考えてください。

そのため、スレッドを作成するクライアント接続が発生するたびに、それをある種のリストに追加してスレッドを開始します。例えば:

クラスのトップで

List<Channel> my_clients = new List<Channel>();

あなたのwhileループで

Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();

次に、特定のクライアントにメッセージを送信する場合。すべてのスレッドをループして、何らかの名前または一意の識別子を持つスレッドを探すことができます。例えば:

for(Channel my_client : my_clients) {
    if(my_client.getName() == "Me") {
        my_client.write("HELLO!");
    }
}

または、同じ息ですべてのクライアントにメッセージを送信できます (ブロードキャスト):

for(Channel my_client : my_clients) {
    my_client.write("HELLO!");
}

クライアントも切断するときは忘れずに削除してください。

// Can't remember the precise exception correct my if I'm wrong!
catch(SocketException ex) {
     my_clients.remove(this);
}

これは、何らかの方法でクライアントの名前を認証して知っているか、何かを送信するように指示されたときに参照する UID をクライアントに提供することを期待していることに注意してください。また、Channel クラスには、念のための Write メソッドがあります。

その助けを願っています!

于 2012-05-18T14:41:18.863 に答える