5

チャット アプリケーションを構築しようとしています。クライアントからサーバーにデータを送信するコードがあります。クライアントが 1 回以上ログインしたとき (クライアント プログラムが 1 回以上実行されたとき)、サーバーは最初の接続以外の残りの接続を受け入れません。これを解決するのを手伝ってくださいここに私のコードがあります:

public class Server
{

//Creating non blocking socket

public void non_Socket() throws Exception {

    ServerSocketChannel ssChannel = ServerSocketChannel.open();
    int port = 80;
    int i=0;
    ssChannel.socket().bind(new InetSocketAddress(port));
    ssChannel.configureBlocking(false);
    while(true)
    {
        SocketChannel sc = ssChannel.accept();`

        if (sc == null) 
        {
            System.out.println("Socket channel is null");
            Thread.sleep(5000);
        }
        else 
        {
            System.out.println("Socket channel is not null");
            System.out.println("Received an incoming connection from " +
                    sc.socket().getRemoteSocketAddress()); 
            new PrintRequest(sc,i).start(); 
            i++;
        }
    }
}

public static void main(String [] abc) throws Exception
{
    new Server().non_Socket();
}
}

class PrintRequest extends Thread {

public  PrintRequest(SocketChannel sc,int i) throws Exception
{
    WritableByteChannel wbc = Channels.newChannel(System.out); 
    ByteBuffer b = ByteBuffer.allocateDirect(1024); // read 1024 bytes 
    int numBytesRead = sc.read(b);

    while (numBytesRead != -1) 
    {
        b.flip();

        while (b.hasRemaining())
        { 
            wbc.write(b);
            System.out.println();
            //System.out.println("Stream  "+i);
            // System.out.println("  KKK   "+b.toString());
        }
        //b.clear();
    }    
}
}

クライアントコード:

public class Client extends Thread {

public void non_Client_Socket() throws Exception
{
    SocketChannel sChannel = SocketChannel.open();
    sChannel.configureBlocking(false);
    sChannel.connect(new InetSocketAddress("localhost", 80));
    while (!sChannel.finishConnect())
    {
        System.out.println("Channel is not connected yet");
    }

    System.out.println("Channel is ready to use");

    /* ----------  going to send data to server ------------*/   
    System.out.println("please enter the text");
    BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
    while(true)
    {
        System.out.println("Enter the text");
        String HELLO_REQUEST =stdin.readLine().toString();
        if(HELLO_REQUEST.equalsIgnoreCase("end"))
        {
            break;
        }

        System.out.println("Sending a request to HelloServer");    
        ByteBuffer buffer = ByteBuffer.wrap(HELLO_REQUEST.getBytes());    
        sChannel.write(buffer); 
     }
}
     /* ----------  the data is written to sChannel server
                      will read from this channel  ------------   */

public static void main(String [] args) throws Exception
{
    new Client().non_Client_Socket();
}
}
4

2 に答える 2

4

ここには多くの問題があります。

  1. ServerSocketChannel非ブロッキング モードにしてからaccept()、セレクターを使用せずに呼び出しています。つまり、99.9999% の確率でaccept()null が返されるため、CPU サイクルを消費しています。これは無意味です。ブロッキング モードで受け入れるか、セレクターを使用します。

  2. クライアントSocketChannelをノンブロッキング モードにし、セレクターを使用せずに呼び出しconnect(),と呼び出しを行います。finishConnect()つまり、99% のfinishConnect()確率で false が返されるため、CPU サイクルを消費しています。これは無意味です。ブロッキング モードで接続するか、セレクタを使用します。

  3. の結果を無視していSocketChannel.write()ます。そんなことはできません。知っておく必要のある情報を返します。

要するに、あなたのコードはあまり意味がありません。

于 2012-06-20T10:01:03.350 に答える
3

あなたのコードを詳しく調べる時間はありませんが、いくつかの最初の観察:

  1. NIO を使用する場合、クライアントごとに 1 つのスレッドではなく (前の質問Selectorで提案したように) 使用することをお勧めします。

  2. サーバーソケットが新しい接続bindを許可するために、各クライアントに覚えておいてください。accept

于 2012-06-19T11:30:30.657 に答える