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 服务器将连接到所有潜在客户端以推送网页 - 跳过所有 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 回答