2008-08-30 19 views
13

Trong dự án tôi đang làm việc, chúng tôi cần phát triển một ứng dụng trò chuyện trên web, không phải là một cuộc trò chuyện rất phức tạp, chỉ là một cách để kết nối hai người nói về một chủ đề rất cụ thể. cần bất kỳ loại xác thực nào cho một trong hai người dùng, chúng tôi không phải hỗ trợ biểu tượng cảm xúc, hình đại diện hoặc nội dung như vậy. Một số thành viên của dự án cho rằng chúng tôi có thể sử dụng XMPP thông qua BOSH, tôi nói nó giống như cố bắt cá bằng thuyền và đề xuất một phương pháp đơn giản hơn, giống như một cuộc trò chuyện web Ajax/MySQL đơn giản, nhưng chúng tôi ' lại lo lắng về hiệu suất hit trong máy chủ vì việc bỏ phiếu liên tục của nhiều cuộc trò chuyện mở cùng một lúc.Ajax polling

Có ai đã làm điều gì đó như thế này trước đây không? Bạn muốn giới thiệu gì?

Trả lời

6

Bạn cũng có thể muốn xem xét Comet.

Nó được sử dụng bởi GTalk, Meebo và nhiều other chat applications. Một vài năm trước đây khi tôi đang thử nghiệm với nó, không có nhiều thư viện hoặc chi tiết về kiến ​​trúc máy chủ để triển khai nó, nhưng có vẻ như có nhiều thứ hơn bây giờ.

Hãy xem dự án cometd để biết thêm thông tin kỹ thuật.

5

Bạn sẽ đề xuất điều gì?

XMPP qua Bosh

Không cần phải phát minh ra định dạng tin nhắn của riêng bạn và giao thức vận chuyển khi người khác có. Nếu bạn cố gắng, nó sẽ phát triển chậm đến mức phức tạp như BOSH nhưng không có lợi ích của việc hỗ trợ hoặc chuẩn hóa thư viện của bên thứ ba.

0

Tôi nghĩ mọi người đã sử dụng cometd cho loại điều này.

2

Bạn cũng có thể muốn xem xét Comet.

Tôi nghĩ mọi người đã sử dụng cometd cho loại điều này.

BOSH là tiêu chuẩn để vận chuyển XMPP qua HTTP. Nó liên quan đến Comet để đẩy dữ liệu cho khách hàng.

1

Tôi đã làm điều tương tự này một vài tháng trước và vui chơi chỉ là chơi xung quanh với các khái niệm. Tôi thực sự đã sử dụng kỹ thuật forever-frame thay vì bỏ phiếu.

Mã bên dưới là tệp "comet" js chứa các khái niệm chung cần thiết để thiết lập "trò chuyện nhóm".

function Comet(key) { 

    var random = key; 
    var title = 'Comet'; 
    var connection = false; 
    var iframediv = false; 
    var browserIsIE = /*@[email protected]*/false; 
    var blurStatus = false; 
    var tmpframe = document.createElement('iframe'); 
    var nl = '\r\n'; 

    this.initialize = function() { 
    if (browserIsIE) { 
     connection = new ActiveXObject("htmlfile"); 
     connection.open(); 
     connection.write("<html>"); 
     connection.write("<script>document.domain = '"+document.domain+"'"); 
     connection.write("</html>"); 
     connection.close(); 
     iframediv = connection.createElement("div"); 
     connection.appendChild(iframediv); 
     connection.parentWindow.comet = comet; 
     iframediv.innerHTML = "<iframe id='comet_iframe' src='./comet.aspx?key="+random+"'></iframe>"; 
    } else { 
     connection = document.createElement('iframe'); 
     connection.setAttribute('id', 'comet_iframe'); 
     iframediv = document.createElement('iframe'); 
     iframediv.setAttribute('src', './comet.aspx?key='+random); 
     connection.appendChild(iframediv); 
     document.body.appendChild(connection); 
    } 
    } 

    // this function is called from the server to keep the connection alive 
    this.keepAlive = function() { 
    if (!browserIsIE) { 
     mozillaHack(); 
    } 
    } 

    // this function is called from the server to update the client 
    this.updateClient = function (value) { 
    var outputDiv = document.getElementById('output'); 
    outputDiv.value = value + nl + outputDiv.value; 
    if (blurStatus == true) { 
     document.title = value; 
    } 
    if (!browserIsIE) { 
     mozillaHack(); 
    } 
    } 

    this.onUnload = function() { 
    if (connection) { 
     // this will release the iframe to prevent problems with IE when reloading the page 
     connection = false; 
    } 
    } 

    this.toggleBlurStatus = function(bool) { 
    blurStatus = bool; 
    } 

    this.resetTitle = function() { 
    document.title = title; 
    } 

    function mozillaHack() { 
    // this hack will fix the hour glass and loading status for Mozilla browsers 
    document.body.appendChild(tmpframe); 
    document.body.removeChild(tmpframe); 
    } 
} 
+0

được kỹ thuật này rquired có tomcat thêm vào thứ ba trên thư viện ..etc sao chổi? hoặc có thể phục vụ trên servlet điển hình? có bất kỳ ứng dụng demo/làm việc nào mà chúng tôi có thể tham khảo không? – cometta

+0

có thể cho chúng ta thấy ví dụ về comet.aspx? – cometta

+0

Kỹ thuật này không yêu cầu bất cứ thứ gì ngoài IIS6 và .NET để khởi động và chạy. –

0

Tôi đồng ý với John. Nhưng có một câu hỏi khác không được trả lời.
Tôi đã làm điều này nhưng thay vì sử dụng cơ sở dữ liệu, chúng tôi đã sử dụng một tệp phẳng, nó cuối cùng đã làm tê liệt máy chủ, nhưng cho đến khi chúng tôi có ~ 450 người dùng hoạt động, và nếu chúng tôi đã thực hiện nó đã tốt hơn.
Điều này đã được thực hiện trên một tài khoản lưu trữ cơ bản từ Godaddy.

Chỉnh sửa: BTW Godaddy có vẻ ít thích thú hơn khi tôi nhận được cuộc gọi điện thoại.

2

Có một máy chủ rất tốt để xử lý thông điệp đẩy từ máy chủ đến trình duyệt (gọi Comet) - Orbited. Nó dễ dàng tích hợp với các công nghệ khác (Django, Rails, PHP, vv) giống như memcached.

Bạn thực sự nên kiểm tra nếu bạn muốn xử lý tải trọng nghiêm trọng. Nếu không, việc bỏ phiếu Ajax đơn giản là cách tốt nhất.

1

Bí quyết là nhận ra rằng lần duy nhất ứng dụng của bạn cần gọi CGI trên máy chủ là khi ai đó nói điều gì đó. Đối với các cuộc thăm dò ý kiến ​​thường xuyên, hãy thăm dò trang tĩnh mà tập lệnh CGI của bạn cập nhật bất cứ khi nào có cuộc trò chuyện mới. Sử dụng các yêu cầu HEAD, so sánh các dấu thời gian với các dấu thời gian được nhìn thấy lần cuối và chỉ thực hiện GET đầy đủ khi những thay đổi đó. Tôi có một ứng dụng trò chuyện ngây thơ đơn giản được thực hiện theo cách này, và việc sử dụng tải và băng thông là không đáng kể đối với vài chục người dùng đồng thời mà chúng tôi có.

3

Nếu bạn không thích ý tưởng bỏ phiếu HTTP, bạn có thể có phim Flash trên trang trò chuyện có kết nối liên tục với một số deamon trên máy chủ, khi đó phim Flash sẽ gọi hàm JavaScript khách hàng cập nhật trò chuyện khi tin nhắn mới xuất hiện. (Trừ khi bạn muốn có giao diện Flash cho cuộc trò chuyện của mình ..)

0

Thanh toán Speeqe. Một số open-source solution cho các phòng trò chuyện dựa trên web sử dụng BOSH và XMPP đằng sau hậu trường.

0

Tôi chỉ tìm thấy bài đăng này, nó cũ, nhưng khái niệm bỏ phiếu mang lại nhiều khó khăn cho rất nhiều bài thơ. Vì vậy, tôi sẽ đặt một ví dụ thực hiện ở đây. Nhưng trước khi đưa nó cho bạn, tôi nên cung cấp cho bạn một lời khuyên khiến tôi nổi giận trước đây:

Khi bạn thăm dò ý kiến, bạn nên quan tâm đến hành vi phiên (race conditions). Để làm cho nó đơn giản: nếu bạn mở một phiên, tệp phiên bị khóa cho đến khi phiên được đóng để tránh 2 người viết ghi dữ liệu khác nhau vào nó. Vì vậy, nếu bạn cần một phiên để kiểm tra xem người dùng đã đăng nhập hay chưa, hãy luôn đóng phiên trước khi bỏ phiếu.

Bản trình diễn của tôi cung cấp cho bạn một ví dụ về triển khai bỏ phiếu trong PHP. Tôi sẽ không sử dụng một cơ sở dữ liệu, mà là một tập tin thay thế. Khi bạn nhấp vào nút bỏ phiếu, bạn sẽ nhập vòng lặp và cho đến khi tệp được sửa đổi, bạn sẽ vẫn bỏ phiếu. Khi bạn điền vào biểu mẫu và nhấp vào Phát hành, những gì bạn đã nhập sẽ được lưu vào tệp. Thời gian sửa đổi của tệp sẽ thay đổi để việc bỏ phiếu sẽ dừng lại.

Mẹo: sử dụng công cụ như Firebug để xem điều gì đang xảy ra.

Bây giờ cho phép nói chuyện trong một Langage tốt hơn so với tiếng anh của tôi:

<?php 

    // For this demo 
    if (file_exists('poll.txt') == false) { 
     file_put_contents('poll.txt', ''); 
    } 

    if (isset($_GET['poll'])) { 

     // Don't forget to change the default time limit 
     set_time_limit(120); 

     date_default_timezone_set('Europe/Paris'); 
     $time = time(); 

     // We loop until you click on the "release" button... 
     $poll = true; 
     $number_of_tries = 1; 
     while ($poll) 
     { 
      // Here we simulate a request (last mtime of file could be a creation/update_date field on a base) 
      clearstatcache(); 
      $mtime = filemtime('poll.txt'); 

      if ($mtime > $time) { 
       $result = htmlentities(file_get_contents('poll.txt')); 
       $poll = false; 
      } 

      // Of course, else your polling will kill your resources! 
      $number_of_tries++; 
      sleep(1); 
     } 

     // Outputs result 
     echo "Number of tries : {$number_of_tries}<br/>{$result}"; 
     die(); 
    } 

    // Here we catch the release form 
    if (isset($_GET['release'])) 
    { 
     $data = ''; 
     if (isset($_GET['data'])) { 
      $data = $_GET['data']; 
     } 
     file_put_contents('poll.txt', $data); 
     die(); 
    } 

?> 

<!-- click this button to begin long-polling --> 
<input id="poll" type="button" value="Click me to start polling" /> 

<br/><br/> 

Give me some text here : 
<br/> 
<input id="data" type="text" /> 
<br/> 

<!-- click this button to release long-polling --> 
<input id="release" type="button" value="Click me to release polling" disabled="disabled" /> 

<br/><br/> 

Result after releasing polling : 
<div id="result"></div> 

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
<script type="text/javascript"> 

// Script to launch polling 
$('#poll').click(function() { 
    $('#poll').attr('disabled', 'disabled'); 
    $('#release').removeAttr('disabled'); 
    $.ajax({ 
     url: 'poll.php', 
     data: { 
      poll: 'yes' // sets our $_GET['poll'] 
     }, 
     success: function(data) { 
      $('#result').html(data); 
      $('#poll').removeAttr('disabled'); 
      $('#release').attr('disabled', 'disabled'); 
     } 
    }); 
}); 

// Script to release polling 
$('#release').click(function() { 
    $.ajax({ 
     url: 'poll.php', 
     data: { 
      release: 'yes', // sets our $_GET['release'] 
      data: $('#data').val() // sets our $_GET['data'] 
     } 
    }); 
}); 

</script> 

Bạn có thể thử nó here