1

教師が文字列メッセージを生徒に送信する学校アプリを作成しました。教師は、ログインしている生徒のハッシュ マップを保持します。教師がタブレットで次のページ コマンドを押すと、生徒には次のページが表示されます。これは通常起こることですが、教師が何らかの理由でハッシュマップ内の 1 人の生徒と接続できない場合、プロセス全体が非常に遅くなり、システムがそれ以上応答しなくなることはめったにありません。

public static void SendToEveryStudent(String message) throws IOException, ELearningException 
{   
    String command;
    String host;
    int port;
    String failedStudents = "";
    int leftOverStudents = 0;
    ApplicationLog.log("Command Queue: sendToEveryStudent : " + message, InitializeTeacherJar.getInstance().isLoggingEnabled());
    int socketTimeout;

    Socket studentSocket = null;

    StudentUtility.studentCounter = 0;

    port = InitializeTeacherJar.getGlobalPort();
    socketTimeout = InitializeTeacherJar.getInstance().getTeacherStudentSocketTimeout();

    // Check if no of students are more then zero
    if (InitializeTeacherJar.getInstance().getStudentIPList().keySet().size() > 0)
    {
        StudentUtility.studentCounter = InitializeTeacherJar.getInstance().getStudentIPList().keySet().size();

        for (String key : InitializeTeacherJar.getInstance().getStudentIPList().keySet())
        {
            try 
            {   
                host = InitializeTeacherJar.getInstance().getStudentIPList().get(key).get(0);

                if (!host.equalsIgnoreCase(""))
                {   
                    if (studentSocket != null)
                    {
                        studentSocket.close();
                        studentSocket = null;
                    }

                    try
                    {   
                        studentSocket = new Socket(InetAddress.getByName(host), port);
                        studentSocket.setSoTimeout(socketTimeout);
                    }
                    catch (Exception e)
                    {
                        leftOverStudents++;
                        failedStudents = key + InitializeTeacherJar.getInstance().getDelimiter();
                        ApplicationLog.log("Exception :: " + host +" is not reachable as the server is down at his end.", InitializeTeacherJar.getInstance().isLoggingEnabled());
                        continue;
                    }

                    if (studentSocket != null)
                    {
                        if (InitializeTeacherJar.getInstance().getStudentIPList().get(key).get(1).equalsIgnoreCase("present"))
                        {
                            studentSocket.getOutputStream().write((message + "\n").getBytes());

                            ApplicationLog.log("Command Queue: Message to student :: " + message + " :: " + key, InitializeTeacherJar.getInstance().isLoggingEnabled());

                            BufferedReader in = new BufferedReader(new InputStreamReader(studentSocket.getInputStream()));

                            String line = null;

                            while ((line = in.readLine()) != null)
                            {
                                if (line.equalsIgnoreCase("ack"))
                                {
                                    //ApplicationLog.log("InitializeTeacherJar :: Student Counter is :: " + StudentUtility.studentCounter, InitializeTeacherJar.getInstance().isLoggingEnabled());
                                    ApplicationLog.log("Command Queue: Ack recvd for :: "+ key + " :: " + host, InitializeTeacherJar.getInstance().isLoggingEnabled());
                                }
                                else
                                {
                                    ApplicationLog.log("Command Queue: Did Not received ACK for :: "+ key + " :: " + host, InitializeTeacherJar.getInstance().isLoggingEnabled());
                                }
                            }
                        }
                        else 
                        {
                            studentSocket.getOutputStream().write((CONSTANTS.ALERT + InitializeTeacherJar.getInstance().getDelimiter() + ErrorCodes.TABLET_NOT_ASSIGNED).getBytes());

                            ApplicationLog.log("StudentUtility :: Tablet not assigned to :: " + key, InitializeTeacherJar.getInstance().isLoggingEnabled());
                        }

                        studentSocket.close();
                    }
                }
            }
            catch (Exception e) 
            {
                ApplicationLog.log("CommandQueue :: sendToEveryStudent Exception :: " + e, InitializeTeacherJar.getInstance().isLoggingEnabled());

                studentSocket.close();
            }

            studentSocket = null;
        }
    }

    if (leftOverStudents > 0)
    {
        failedStudents = StudentUtility.m_stripLastChar(failedStudents);

        ApplicationLog.log("SendToEveryStudent :: Some Students Were Not Connected :: " + ErrorCodes.TEACHER_STUDENT_SOCKET_NOT_CONNECTED + InitializeTeacherJar.getInstance().getDelimiter() + failedStudents, InitializeTeacherJar.getInstance().isLoggingEnabled());

        InitializeTeacherJar.getInstance().getMyFlexSocket().getOutputStream().write((CONSTANTS.ALERT + InitializeTeacherJar.getInstance().getDelimiter() + ErrorCodes.TEACHER_STUDENT_SOCKET_NOT_CONNECTED + InitializeTeacherJar.getInstance().getDelimiter() + failedStudents + InitializeTeacherJar.getInstance().getCommandDelimeter()).getBytes());
        InitializeTeacherJar.getInstance().getMyFlexSocket().getOutputStream().flush();         
    }
    else if (leftOverStudents == 0)
    {
        InitializeTeacherJar.getInstance().getMyFlexSocket().getOutputStream().write((CONSTANTS.ALERT + InitializeTeacherJar.getInstance().getDelimiter() + CONSTANTS.SENT_SUCCESSFULLY_TO_ALL + InitializeTeacherJar.getInstance().getDelimiter() + "Sent To All" + InitializeTeacherJar.getInstance().getCommandDelimeter()).getBytes());
        InitializeTeacherJar.getInstance().getMyFlexSocket().getOutputStream().flush();
    }

    StudentUtility.studentCounter = StudentUtility.studentCounter - leftOverStudents;
    }
}

私の不安が横たわっている領域は

1) ループ - ソケットを作成し、ブロッキング呼び出しを呼び出します。つまり、受け入れるループは、AsynTask に入れます。2) SocketTimeout - 最小限の必要があります。現在は 1.2 秒です。これの最適値はどれくらいですか?

これは少し多すぎるコードかもしれませんが、説明が役立つことを願っています。事前に感謝します。

4

2 に答える 2

1

これは一種の後方設定です。潜在的なすべてのクライアントに接続して Web ページをプッシュする Web サーバーを想像してみてください。NAT/ファイアウォールの問題はすべてスキップされます。これは、スケーリングせず、シーケンシャル シングルスレッドでリストの先頭に遅延が発生しやすい問題です。実装とマルチスレッド設定でのリソースの浪費。

教師がサーバーであり、生徒がオンデマンドで接続するクライアントである、従来のクライアント サーバー モデルに切り替えることをお勧めします。

于 2012-12-18T14:58:21.170 に答える
0

当分の間、私はそれを終わらせるためにシムを持っています。ただし、ソフトウェアのリリース予定が終わったら、「ライブソケットのコレクション」を試すつもりです。

とにかく、私がやったことは、上記のコードへの変更に従うことです:

                try
                {   
                    inAddress = InetAddress.getByName(host);

                    if (!inAddress.isReachable())
                    {
                       leftOverStudents++;
                       failedStudents = key + InitializeTeacherJar.getInstance().getDelimiter();
                       ApplicationLog.log("Exception :: " + host +" is not reachable as the server is down at his end.", InitializeTeacherJar.getInstance().isLoggingEnabled());
                       continue; 
                    }

                    studentSocket = new Socket(inAddress, port);
                    studentSocket.setSoTimeout(socketTimeout);
                }

到達できない場合は、次の学生に移動するだけです。とにかく助けてくれてありがとう。

于 2012-12-23T08:50:35.317 に答える