序章
私は2つの目的でXMPPを使用しているMVCWebアプリに取り組んでいます:1)サーバーからクライアントへのリアルタイムデータの通信-XMPPMessaging 2)ユーザーグループチャット-XMPPChat
クライアント側でStrophe.jsを使用し、サーバー側でMatriX C#ライブラリを使用しています。XMPPChatは、サーバー側で事前にバインドし、接続情報をクライアントに渡すことでセットアップされます。クライアントは、stropheに接続します。XMPPMessagingは事前バインドではなく、クライアント側でログインするだけです。ユーザーが開くすべてのウィンドウは、サーバーからデータを受信するために新しいXMPPMessagingインスタンスに接続します。チャットウィンドウのみがXMPPChatとXMPPMessagingを接続します。また、どちらもBOSHを介してPunjab接続マネージャーに接続しており、BOSHはメッセージをOpenfireサーバーに転送しています。
問題
現在、Internet Explorerでのみ発生する問題があります(IE8とIE9でテストしており、どちらもこの問題を示しています)。XMPPMessagingとXMPPChatを接続すると、非常に大きな遅延(10秒-2分)後にチャットメッセージが送信されます。これにより、XMPPChatでも切断の問題が発生することを確認しました。受信機能はうまく機能します。他のブラウザがチャットルームに投稿した場合、IEは他の人と同じようにすぐにそれを取得します。XMPPMessagingがオフになっている場合、チャット送信は遅延や切断なしで正常に実行されます。ブレークポイントを使用してコードをステップ実行しましたが、送信機能がすぐに起動します。パンジャブのログも観察しましたが、パンジャブはそうではないようです。
IEの同時BOSH接続が干渉するこのような問題を他の誰かが見たことがあるかどうか、私は主に疑問に思っています。
アップデート
IEのチャット機能は、今日、完全に不可解に機能し始めました。コードやその構成はまったく変更していません。メッセージング接続とチャット接続の両方が実行されており、両方が接続されていることを再確認しました。修正を診断するために、Apacheを再起動するとバグが再発しましたが、IEでのみ、チャットの速度が大幅に低下し、ランダムに切断されました。
アップデート2-他のブラウザで見る
今日、他のタブで複数のチャットインスタンスを開くことで、他のブラウザ(Chrome、Firefox)で問題を再現することができました。したがって、IEはこの問題でさらに悪化したようです。1つのタブを開くだけで済みます。これは、ブラウザの同時接続制限の問題に私を向けていますが、2つの接続で制限の近くにいるべきではないことを考えると、それは意味がありません。
アップデート3-他のブラウザで原因が特定
Firefoxでテストを実行して、同時接続の問題に対処している疑いがあることを確認しました。チャットタブを1つ開くと、メッセージがすぐに投稿されました。私は2つ目を開きましたが、予想どおり、遅れました。次に、 about:configを開き、 network.http.max-persistent-connections-per-serverを6から7に変更しました。これを行った後、テストを繰り返しました。1つ目と2つ目のチャットタブの両方でメッセージを瞬時に投稿できましたが、3つ目のタブを開くと、すべてのタブで遅延が発生し始めました。IEでテストして、FEATURE_MAXCONNECTIONSPERSERVERレジストリ設定を変更し、問題が解決するかどうかを確認して、これが同じ問題であるかどうかを確認します。
アップデート4-IEの問題はまだ解決されていません
IEで同じテストを実行し、ここに示すようにレジストリを変更し、0xAに設定されたFEATURE_MAXCONNECTIONSPERSERVERおよびFEATURE_MAXCONNECTIONSPER1_0SERVERレジストリにiexplorer.exe DWORD設定を追加しましたが、動作に変化は見られません。x64設定(Wow6432Nodeの下)で同じことを試しましたが、それでも変化は見られませんでした。また、元のexplorer.exeの値を2または4から8に変更しようとしましたが、変更するたびにコンピューターを再起動した後も、動作に変化は見られませんでした。
コード
参考までに、関連する場合と関連しない場合があるXMPPチャットコードの一部を次に示します。
XMPPAttach: function (jid, sid, rid) {
connection = new Strophe.Connection(BOSH_SERVICE);
connection.rawInput = function (data) {
log('RECV: ' + data);
};
connection.rawOutput = function (data) {
log('SENT: ' + data);
};
MY_JID = jid;
connection.addHandler(notifyUser, null, 'message', 'chat', null, null);
connection.addHandler(groupChat, null, 'message', 'groupchat', null, null);
connection.addHandler(presenceInfo, null, 'presence', null, null, null);
connection.ping.addPingHandler(pingHandler);
connection.attach(jid, sid, rid, onConnect, 300);
}
function onConnect(status) {
switch (status) {
case Strophe.Status.CONNECTED:
log('CONNECTED');
break;
case Strophe.Status.ERROR:
log('ERROR');
break;
case Strophe.Status.CONNFAIL:
log('CONNFAIL');
break;
case Strophe.Status.AUTHENTICATING:
log('AUTHENTICATING');
break;
case Strophe.Status.AUTHFAIL:
log('AUTHFAIL');
break;
case Strophe.Status.CONNECTING:
log('CONNECTING');
break;
case Strophe.Status.DISCONNECTED:
log('DISCONNECTED');
break;
case Strophe.Status.DISCONNECTING:
log('DISCONNECTING');
break;
case Strophe.Status.ATTACHED:
log('ATTACHED');
break;
default:
log('UKNOWN STATUS CODE');
break;
}
if ((status == Strophe.Status.CONNECTED || status == Strophe.Status.ATTACHED) && !presenceSent) {
connection.send($pres().tree());
presenceSent = true;
userLogin();
}
else if (status == Strophe.Status.CONNECTING || status == Strophe.Status.AUTHENTICATING) {
// do nothing
}
else if (status == Strophe.Status.AUTHFAIL) {
userInvalidLogin();
}
else {
userLoginFailed();
}
}
EnterChatRoom: function (room, nick) {
ROOM_JID = room;
MY_NICK = nick;
var chatJID = room.concat('/', nick);
var pres = $pres({ to: chatJID }).c('x', { xmlns: 'http://jabber.org/protocol/muc' });
connection.send(pres);
}
SendToRoom: function (text) {
var send = $msg({ to: ROOM_JID, type: 'groupchat' }).c('body', {}, text);
connection.send(send.tree());
},
そして、これが私のXMPPメッセージングコードの一部です。
function initializeXMPP() {
connection = new Strophe.Connection(BOSH_SERVICE);
intentionalDisconnect = false;
connection.rawInput = function (data) {
log('RECV: ' + data);
};
connection.rawOutput = function (data) {
log('SENT: ' + data);
};
connection.addHandler(onMessage, null, 'message', null, null, null);
connection.ping.addPingHandler(pingHandler);
connection.connect(messageCatcher.serverSettings.clientUser + '@' + messageCatcher.serverSettings.xmppDomain,
messageCatcher.serverSettings.clientUserPassword,
onConnect, 300, undefined, messageCatcher.serverSettings.route);
log('Strophe is connected.');
}
function onConnect(status) {
switch (status) {
case Strophe.Status.ERROR: // 0
log('ERROR');
StandardErrorHandler({ "Message": "XMPP Connection Error", "Status": "ERROR" });
break;
case Strophe.Status.CONNECTING: // 1
log('CONNECTING');
break;
case Strophe.Status.CONNFAIL: // 2
log('CONNFAIL');
StandardErrorHandler({ "Message": "XMPP Connection Error", "Status": "CONNFAIL" });
break;
case Strophe.Status.AUTHENTICATING: // 3
log('AUTHENTICATING');
break;
case Strophe.Status.AUTHFAIL: // 4
log('AUTHFAIL');
StandardErrorHandler("XMPP AUTHFAIL");
break;
case Strophe.Status.CONNECTED: // 5
log('CONNECTED');
callHandlers(connectHandlers);
break;
case Strophe.Status.DISCONNECTED: // 6
log('DISCONNECTED');
onDisconnect();
break;
case Strophe.Status.DISCONNECTING: // 7
log('DISCONNECTING');
break;
case Strophe.Status.ATTACHED: // 8
log('ATTACHED');
break;
default:
log('UKNOWN STATUS CODE');
break;
}
if (status == Strophe.Status.CONNECTED && !presenceSent) {
var pres = $pres({
//type: 'available'
});
connection.send(pres);
presenceSent = true;
log("PRESENCE SENT - SID: " + connection.sid);
}
}