Все дело в дизайне вашего протокола.
Сокеты предназначены для имитации работы последовательных интерфейсов - данные поступают по 8 бит за раз и ... больше ничего. Сокеты не имеют понятия сообщений - только байты. Думайте о сокетах как о клавиатуре USB. Ваше программное обеспечение получает только байты, поскольку пользователи вводят одну букву за раз (иногда ваше программное обеспечение получает группы байтов, если пользователь набирает достаточно быстро или продолжает нажимать клавишу). Вам нужно решить, из чего состоит «пакет». Предложение? Тогда ваше программное обеспечение должно обнаружить полные остановки "."
. Линия? Затем вы обнаруживаете новые строки.
Ниже приведен простой пример клиента HTTP 1.0 (основное отличие состоит в том, что HTTP 1.0 сигнализирует об окончании пакета, закрывая соединение, а HTTP 1.1 отправляет заголовок Content-Length):
function HTTP_1_0_client (url) {
let urlParts = url.match(/http:..([^/]+)(.*)/);
let domain = urlParts[1];
let path = urlParts[2];
return new Promise((resolve, reject) => {
let rawString = '';
const client = net.createConnection(80, domain);
client.write('GET ' + path + ' HTTP/1.0\n\n');
client.on('data', buf => rawString += buf.toString());
client.on('end', () => {
// headers and body are separated by two newlines:
let httpParts = rawString.match(/^(.+)\r?\n\r?\n(.*)/);
let headers = httpParts[1].split(/\r?\n/);
let text = httpParts[2];
// first line of response is the status line:
let statusLine = headers.shift();
let status = statusLine.match(/^[0-9]+/)[0];
// return the response to the promise:
resolve({
status: status,
headers: headers,
responseText: text
});
});
client.on('error', err => reject(err));
});
}
В приведенном выше протоколе мы просто используем сокетное соединение в качестве конца пакета - таким образом, конец ответа. Вы можете использовать другие условия, чтобы определить конец цикла ответа и вернуть ответ. Все зависит от дизайна протокола.
Ниже приведен еще один простой протокол, который просто использует формат JSON для определения пакета:
function JSONclient (host, port, requestData) {
return new Promise((resolve, reject) => {
let rawString = '';
const client = net.createConnection(port, host);
client.write(JSON.stringify(requestData));
client.on('data', buf => {
rawString += buf.toString();
try {
let response = JSON.parse(rawString);
// If we get here it means no errors
// which means packet is complete -
// return response to promise:
resolve(response);
client.destroy(); // close connection
}
catch (err) {
// Ignore parse error
// It just means packet isn't complete yet.
}
});
client.on('error', err => reject(err));
});
}