私は Node.js (より大きなアプリケーションの特定のケース) に小さなスクリプトを持っています。これは特定のサービスに接続し、定期的に単純な JSON コマンドを送信します。リクエストは「同期的に」送信されるため、最後のレスポンスを受信した後に次のリクエストが送信されます。
残念ながら、時々応答を受け取れません (TCP PUSH がサーバーに送信され、スクリプトは ACK を受信しますが、サーバーからの PUSH はありません)。したがって、スクリプトがハングします。サーバーのバグを示唆していますが、同じスクリプトがPythonでも書かれており、完全に機能します-すべてのリクエストが応答を受け取ります(Pythonスクリプトは17時間以上機能していますが、Node.jsのスクリプトはハングします場合によっては 15 分から 2 時間かかることもあります)。
通信は TLS (node では tls モジュール、python では ssl モジュール) を使用して暗号化されます。観察された唯一の違いは、SSL パケットのサイズにあります。Node の req/res ペアの重量は 53/77 バイトですが、Pythonic スクリプトでは 90/85 バイトです。
サーバーはC#で書かれていますが、それ以上の情報もアクセスもありません(秘密鍵にも到達できません-何が送信されるかを確認します)。
Node で応答を待たない状況もテストしました (write() の呼び出しで小さな関数で setInterval を使用しただけです)。2 ~ 3 つの要求が連続して送信され、そのときだけ応答が返されることがあります。ただし、それらの一部は形式が正しくありません (コンテンツの代わりにメッセージセパレーターのみを受信します。これはサーバー側の問題を示唆していますが、Pythonic バージョンでは表示されません)。
何を提案しますか?この問題は SSL/TLS に関連している可能性がありますか? .NET で何か?それともノード?ご提案いただきありがとうございます。
Node.js のコード:
const tls = require('tls');
var carrier = require('carrier');
var client = tls.connect(1111, 'host', {rejectUnauthorized: false}, function() {
var reqNum = 0;
var resCarrierNum = -1; // because there is additional login message
var resClientNum = -1;
client.on('data', function(data) {
resClientNum++;
setTimeout(function() {
client.write('{"command":"getVersion"}');
reqNum++;
}, 400);
});
carrier.carry(client, function(data) {
console.log(data);
var response = JSON.parse(data);
if(!response.status) {
console.log('ERROR' + response.errorCode + ': ' + (response.errorDescr));
}
resCarrierNum++;
}, "utf8", /\n\n/);
client.write(JSON.stringify({
"command" : "login",
"arguments" : {
"userId" : 1,
"password" : ''
}
}));
});
Python のコード:
import socket
import ssl
import sys
import time
addr = sys.argv[1]
port = int(sys.argv[2])
delay = int(sys.argv[3])
def getDateOfBuild(sslS, counter):
print 'Try', counter, time.asctime()
sslS.send('{"command":"getVersion"}')
sf = sslS.makefile()
while True:
line = sf.readline()
if line == '\n':
break;
if line == '':
print "ERROR: connection closed,", time.asctime()
sys.exit()
print line
s = socket.socket()
sslS = ssl.wrap_socket(s)
sslS.connect((addr, port))
print 'Connected from', sslS.getsockname()
print repr(sslS.getpeername())
counter = 0
sslS.write('{\"command\":\"login\",\"arguments\":{\"userId\":\"\",\"password\":\"\"}}\n')
while True:
getDateOfBuild(sslS, counter)
counter += 1
time.sleep(0.4)
コマンドにはわずかな違いがありますが、まったく同じ文字列を持つバージョンがテストされ、同じ結果が得られました。