NodeJS - "소켓 전화 끊기"가 실제로 무엇을 의미합니까?
Node와 Cheerio를 사용하여 웹 스크레이퍼를 만들고 있는데 특정 웹 사이트에 대해 다음 오류가 발생합니다(이 오류는 이 웹 사이트에서만 발생하며 다른 웹 사이트에서는 스크레이퍼를 사용하지 않습니다).
매번 다른 장소에서 발생하기 때문에 가끔은 힘들 때가 있습니다.url x
다른 때는 오류를 던집니다.url x
괜찮습니다. 그리고 완전히 다른 URL입니다.
Error!: Error: socket hang up using [insert random URL, it's different every time]
Error: socket hang up
at createHangUpError (http.js:1445:15)
at Socket.socketOnEnd [as onend] (http.js:1541:23)
at Socket.g (events.js:175:14)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:910:16
at process._tickCallback (node.js:415:13)
디버깅하기가 매우 까다롭기 때문에 어디서부터 시작해야 할지 잘 모르겠습니다.먼저 소켓 절단 오류란 무엇입니까?404 오류인가요?아니면 서버가 연결을 거부했다는 뜻입니까?
어디에서도 이것에 대한 설명을 찾을 수가 없어요!
편집: 다음은 오류를 반환하는 코드 샘플입니다.
function scrapeNexts(url, oncomplete) {
request(url, function(err, resp, body) {
if (err) {
console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
errors.nexts.push(url);
}
$ = cheerio.load(body);
// do stuff with the '$' cheerio content here
});
}
연결을 닫을 수 있는 직접 통화는 없지만 사용 중인 것으로 알고 있습니다.http.get
그래서 이것은 필요하지 않습니다, 제가 틀렸다면 고쳐주세요!
EDIT 2: 여기 오류를 일으키는 실제 사용 중인 코드가 있습니다. prodURL
및 기타 변수는 대부분 이전에 정의된 jquery selector입니다.노드용 라이브러리를 사용합니다.
function scrapeNexts(url, oncomplete) {
request(url, function (err, resp, body) {
if (err) {
console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
errors.nexts.push(url);
}
async.series([
function (callback) {
$ = cheerio.load(body);
callback();
},
function (callback) {
$(prodURL).each(function () {
var theHref = $(this).attr('href');
urls.push(baseURL + theHref);
});
var next = $(next_select).first().attr('href');
oncomplete(next);
}
]);
});
}
.socket hang up
던져집니다.
고객일 때
클라이언트로서 원격 서버에 요청을 보내도 적시에 응답을 받지 못할 때소켓이 종료되어 이 오류가 발생합니다.이 오류를 발견하고 처리 방법을 결정해야 합니다. 요청을 다시 시도할지, 나중에 대기열에 저장할지 등입니다.
서버/프록시인 경우
서버 또는 프록시 서버인 사용자가 클라이언트로부터 요청을 수신한 후 클라이언트에 대해 작업을 시작하거나 요청을 업스트림 서버로 릴레이하고 응답을 준비하기 전에 클라이언트는 요청을 취소/중지하기로 결정합니다.
이 스택 추적은 클라이언트가 요청을 취소할 때 발생하는 작업을 보여줍니다.
Trace: { [Error: socket hang up] code: 'ECONNRESET' }
at ClientRequest.proxyError (your_server_code_error_handler.js:137:15)
at ClientRequest.emit (events.js:117:20)
at Socket.socketCloseListener (http.js:1526:9)
at Socket.emit (events.js:95:17)
at TCP.close (net.js:465:12)
선http.js:1526:9
한 동한점을 점socketCloseListener
@Blender가 언급한, 특히:
// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());
...
function createHangUpError() {
var error = new Error('socket hang up');
error.code = 'ECONNRESET';
return error;
}
이것은 클라이언트가 브라우저의 사용자인 경우에 일반적인 경우입니다.일부 리소스/페이지를 로드하는 요청은 시간이 오래 걸리고 사용자는 페이지를 새로 고치기만 하면 됩니다.이러한 작업을 수행하면 이전 요청이 중단되고 서버 측에서 이 오류가 발생합니다.
이 오류는 고객의 희망에 의해 발생하기 때문에, 그들은 어떠한 오류 메시지도 받지 않을 것으로 예상합니다.따라서 이 오류를 중요한 오류로 간주할 필요가 없습니다.그냥 무시해.이것은 그러한 오류에 의해 격려됩니다.res
클라이언트가 수신한 소켓은 여전히 쓰기 가능하지만 손상되었습니다.
console.log(res.socket.destroyed); //true
따라서 응답 개체를 명시적으로 닫는 것 외에는 아무것도 보낼 필요가 없습니다.
res.end();
그러나 이미 요청을 업스트림으로 릴레이한 프록시 서버인 경우에는 내부 요청을 업스트림으로 중단하여 응답에 대한 관심이 부족함을 표시해야 하며, 이는 결국 업스트림 서버에 고가의 작업을 중지하도록 지시할 것입니다.
function socketCloseListener() {
var socket = this;
var parser = socket.parser;
var req = socket._httpMessage;
debug('HTTP socket close');
req.emit('close');
if (req.res && req.res.readable) {
// Socket closed before we emitted 'end' below.
req.res.emit('aborted');
var res = req.res;
res.on('end', function() {
res.emit('close');
});
res.push(null);
} else if (!req.res && !req._hadError) {
// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());
req._hadError = true;
}
}
메시지는 서버가 응답을 발송하지 않을 때 발송됩니다.
한 가지 언급할 가치가 있는 사례: Express를 사용하여 Node.js에서 Node.js로 연결할 때 요청된 URL 경로에 "/"를 접두사로 붙이지 않으면 "소켓 전화 끊기"가 발생합니다.
아래 예제에서 주석이 달린 코드를 추가하지 못했을 때 동일한 오류가 발생한 간단한 예입니다.코드 주석 달기req.end()
이 문제를 해결합니다.
var fs = require("fs");
var https = require("https");
var options = {
host: "en.wikipedia.org",
path: "/wiki/George_Washington",
port: 443,
method: "GET"
};
var req = https.request(options, function (res) {
console.log(res.statusCode);
});
// req.end();
나는 https 서비스를 소비하곤 했고 그것은 ""를 socket hang up
보여주었습니다.
그 다음에 저는 로 바꿨고, 작동하고 있습니다.
블렌더의 답변을 확장하면 여러 상황에서 이러한 현상이 발생합니다.제가 마주치는 가장 일반적인 것은 다음과 같습니다.
- 서버가 손상되었습니다.
- 연결을 했으며, "" " " "에 의해 입니다. 아마도 다음에 의해 차단되었을 것입니다.
User-Agent
.
socketCloseListener
블렌더의 답변에 요약되어 있듯이, 전화 끊기 오류가 발생하는 유일한 장소는 아닙니다.
예를 들어, 다음과 같이 확인할 수 있습니다.
function socketOnEnd() {
var socket = this;
var req = this._httpMessage;
var parser = this.parser;
if (!req.res) {
// If we don't have a response then we know that the socket
// ended prematurely and we need to emit an error on the request.
req.emit('error', createHangUpError());
req._hadError = true;
}
if (parser) {
parser.finish();
freeParser(parser, req);
}
socket.destroy();
}
시도해 볼 수 있습니다.curl
노드에서 전송되는 헤더 등을 포함하여 응답이 있는지 확인합니다.다음과 같은 응답이 없는 경우curl
하지만 브라우저에서 응답을 받고 나면,User-Agent
헤더가 차단될 가능성이 높습니다.
OS 의 경우) 로, 예를 들어 언할가있또다는사른례다 (Linux 및 OS X 우경니경입우사다는용하를리)와 같은 를 들 수 .https
요청을 수행하기 위해 또는 통과할 경우https://...
제공되는 의 URL로 로로제는로인스 URL 의됩사니를 .443
예약된 전용 포트이며, 당신이 포트에 도착할 수도 있습니다.Socket hang up
또는ECONNREFUSED
오류
포트 신포트사를 합니다.3000
를 하고 f.e.를 .http
부탁한다.
위해서request
명령어
제한 시간
연결 제한 시간과 읽기 제한 시간의 두 가지 주요 유형이 있습니다.클라이언트가 원격 컴퓨터에 대한 연결을 설정하는 동안 시간 초과가 발생하면 연결 시간 초과가 발생합니다.
connect()
소켓에서 호출).서버가 응답의 일부를 다시 보내기에 너무 느릴 때마다 읽기 시간 초과가 발생합니다.
연결 시간 초과는 다음을 발생시킵니다.ETIMEDOUT
오류 및 읽기 시간 초과가 발생합니다.ECONNRESET
message
이로 인해 문제가 발생했습니다. 여기 나열된 모든 작업을 수행하면서도 오류가 발생했습니다.req.abort()를 호출하면 ECONNRESET 코드와 함께 오류가 발생하므로 오류 처리기에서 이를 파악해야 합니다.
req.on('error', function(err) {
if (err.code === "ECONNRESET") {
console.log("Timeout occurs");
return;
}
//handle normal errors
});
나는 카우치 DB에 연결하기 위해 나노 라이브러리를 사용하는 동안 같은 문제를 겪었습니다.keepalive 에이전트 라이브러리를 사용하여 연결 풀링을 미세 조정하려고 했지만 소켓이 끊기는 메시지와 함께 계속 실패했습니다.
var KeepAliveAgent = require('agentkeepalive');
var myagent = new KeepAliveAgent({
maxSockets: 10,
maxKeepAliveRequests: 0,
maxKeepAliveTime: 240000
});
nano = new Nano({
url : uri,
requestDefaults : {
agent : myagent
}
});
약간의 고군분투 끝에 저는 그 문제를 해결할 수 있었습니다. 그것이 밝혀졌기 때문에 그것은 매우 단순한 실수였습니다.HTTPS 프로토콜을 통해 데이터베이스에 연결하고 있었지만, 이 라이브러리의 사용 예에서 볼 수 있듯이 생성된 킵얼라이브 에이전트를 계속 나노 개체에 전달했습니다(http를 사용하는 일부 기본값에 의존함).
Https 에이전트를 사용하기 위한 한 가지 간단한 변경은 다음과 같습니다.
var KeepAliveAgent = require('agentkeepalive').HttpsAgent;
"소켓 전화 끊기"는 서버 끝에서 연결이 종료되었음을 나타내는 상당히 일반적인 오류라고 생각합니다.즉, 클라이언트와 서버 간의 연결을 유지하는 데 사용되는 소켓의 연결이 끊어졌습니다.(위에서 언급한 많은 점들이 다양한 사람들에게 도움이 된다고 확신하지만, 저는 이것이 더 일반적인 대답이라고 생각합니다.)
저의 경우, 저는 페이로드가 20K를 초과하는 요청을 보내고 있었습니다.서버에서 거부되었습니다.요청이 성공할 때까지 텍스트를 제거하고 다시 시도하여 확인했습니다.최대 허용 길이를 결정한 후, 저는 단일 문자를 추가하면 오류가 발생하는 것을 확인했습니다.저는 또한 Python 앱과 Postman에서 동일한 요청을 보내 클라이언트가 문제가 아니라는 것을 확인했습니다.그래서 어쨌든, 저는 제 경우에, 탑재체의 길이가 저의 구체적인 문제였다고 확신합니다.
다시 한 번 말하지만, 문제의 근원은 일화입니다.일반적인 문제는 "Server Says No"입니다.
나는 어떤 서버에 요청하는 동안 같은 문제를 겪었습니다.제 경우, 요청 옵션의 헤더에서 User-Agent 값을 설정하는 것이 도움이 되었습니다.
const httpRequestOptions = {
hostname: 'site.address.com',
headers: {
'User-Agent': 'Chrome/59.0.3071.115'
}
};
일반적인 경우는 아니며 서버 설정에 따라 다릅니다.
는 이오는작시발수있습다니생할에로 할 때도 할 수 .http.request
아마도 당신의 요청이 아직 끝나지 않았을 것입니다.
예:
const req = https.request(options, res => {})
다음해야 합니다: 항 다 합 니 다 야 해 추 가 행 을 상 음req.end()
이 기능으로 우리는 요청 발송을 완료하도록 주문할 것입니다.
설명서에 나와 있는 것처럼:
http.request()를 사용하면 요청 본문에 기록되는 데이터가 없더라도 항상 req.end()를 호출하여 요청의 끝을 표시해야 합니다.
는 또한이사때수문있다니습일용는유다있니수▁using▁of▁be를 사용하기 때문일 수.app
예express
에 server
const server = http.createServer(app)
서버 소켓을 만드는 동안.
틀렸어
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
app.use(function (req, res) {
res.send({ msg: "hello" });
});
const wss = new WebSocket.Server({ server: app }); // will throw error while connecting from client socket
app.listen(8080, function listening() {
console.log('Listening on %d', server.address().port);
});
맞아요.
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
app.use(function (req, res) {
res.send({ msg: "hello" });
});
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
server.listen(8080, function listening() {
console.log('Listening on %d', server.address().port);
});
시간이 오래 걸렸지만 다른 경우는 서버 측에서 시간이 오래 걸리고(익스프레스의 기본값인 2분 이상) 서버 측에서 시간 초과 매개 변수가 구성되지 않은 경우입니다.저의 경우 client->server->server request(Node.js express)를 수행하고 있었는데 서버와 클라이언트의 각 요청 라우터에 timeout 매개 변수를 설정해야 합니다.그래서 두 서버 모두에서 다음을 사용하여 요청 시간 제한을 설정해야 했습니다.
req.setTimeout([your needed timeout])
라우터에 있습니다.
과 안드로이드 개발을 함께 하는데, 둘포트 8601을 했습니다.socket hang up
오류, Android Studio 장치 시뮬레이터를 닫은 후 노드 측에서 잘 작동합니다.Android Studio 장치 시뮬레이터와 도커를 함께 사용하지 마십시오.
여기에 한 가지 추가 사례가 있는 것 같습니다. 전자가 "localhost" 도메인 이름의 팬이 아니라는 것입니다.저의 경우 이를 변경해야 했습니다.
const backendApiHostUrl = "http://localhost:3000";
대상:
const backendApiHostUrl = "http://127.0.0.1:3000";
그 후에 그 문제는 그냥 사라졌습니다.
이는 DNS 확인(로컬 또는 원격)도 일부 문제를 일으킬 수 있음을 의미합니다.
OCP 클러스터에서 CouchDB를 사용할 때도 비슷한 오류가 발생했습니다.
const cloudantSessionStore = sessionStore.createSessionStore(
{
type: 'couchdb',
host: 'https://' + credentials['host'],
port: credentials['port'],
dbName: 'sessions',
options: {
auth: {
username: credentials['username'],
password: credentials['password']
},
cache: false
}
}
CouchDB 인스턴스에 연결하려면 "https"가 아니라 "http"여야 합니다.유사한 문제에 직면한 모든 사람에게 도움이 되기를 바랍니다.
nodejs에서 axios를 사용하다가 url에서 데이터를 가져오는 동안 소켓 절단 오류가 발생했습니다.
const response = await axios.get(url)
시간 초과 오류로 인해 오류를 처리하지 못한 것으로 드러났습니다.
그래서 다음 코드 스니펫과 같이 타임아웃 및 오류 처리를 추가했습니다.
const response = await axios
.get(url, { timeout: 10000 })
.catch((error) => {
if (axios.isAxiosError(error)) {
const axiosError = error as AxiosError;
console.log(message, axiosError.message);
console.log(axiosError.response);
});
그래서 오류를 처리하고 타임아웃을 지정하는 것으로 소켓 절단 문제를 해결했습니다.
저의 경우, 애플리케이션/json 응답의 형식이 잘못되었기 때문입니다(스택 추적 포함).응답이 서버로 전송되지 않았습니다.로그가 없었기 때문에 디버깅하기가 매우 까다로웠습니다.이 스레드는 무슨 일이 일어나는지 이해하는 데 많은 도움이 됩니다.
node-http-http-http를 사용하는 경우 소켓 연결 끊기 오류가 발생할 수 있는 이 문제에 유의하십시오. https://github.com/nodejitsu/node-http-proxy/issues/180
해결을 위해 이 링크에서도 express 앞에 있는 express 경로 내에서 API 경로(프록시용)를 선언하여 이동하기만 하면 됩니다.bodyParser().
어제 IntelliJ IDEA 2016.3.6을 통해 웹 애플리케이션과 node.js 서버를 실행하는 중에 이 문제가 발생했습니다.제가 해야 할 일은 크롬 브라우저에서 쿠키와 캐시를 지우는 것이었습니다.
https 연결을 통해 이 오류가 발생하고 즉시 발생하는 경우 SSL 연결을 설정하는 데 문제가 있을 수 있습니다.
저에게는 이번 호 https://github.com/nodejs/node/issues/9845 이었지만, 당신에게는 다른 문제일 수도 있습니다.SSL에 문제가 있는 경우 도메인에 연결하려고 시도하는 nodejsl/ssl 패키지로 SSL을 복제할 수 있어야 합니다.
주목할 만한 가치가 있다고 생각합니다...
저는 구글 API를 위한 테스트를 만들고 있었습니다.저는 임시 서버로 요청을 가로채서 실제 api로 전달하고 있었습니다.요청에 있는 헤더만 전달하려고 했는데, 몇 개의 헤더로 인해 다른 쪽에서 express에 문제가 발생했습니다.
다시 말해, 나는 삭제해야 했습니다.connection
,accept
,그리고.content-length
요청 모듈을 사용하여 전달하기 전에 헤더를 입력합니다.
let headers = Object.assign({}, req.headers);
delete headers['connection']
delete headers['accept']
delete headers['content-length']
res.end() // We don't need the incoming connection anymore
request({
method: 'post',
body: req.body,
headers: headers,
json: true,
url: `http://myapi/${req.url}`
}, (err, _res, body)=>{
if(err) return done(err);
// Test my api response here as if Google sent it.
})
제 경우는 오류가 아니라 크롬 브라우저에서 예상되는 동작이었습니다.Chrome은 속도를 위해 tls 연결을 유지하지만 node.js 서버가 2분 후에 연결을 중지하고 오류가 발생합니다.
엣지 브라우저를 사용하여 GET 요청을 시도하면 오류가 전혀 발생하지 않습니다.크롬 창을 닫으면 바로 오류가 발생합니다.
그래서 어떻게 해야 할까요? 1)실제로 오류가 아니기 때문에 이 오류를 필터링할 수 있습니다. 2)아마 더 나은 해결책이 있을 것입니다 :)
코드, 문자열,등으로 후 번호로 에만 JS , mongodb 결열자문, CORS 확인그전포로환호번트server.listen(port);
그것을 작동하게 만들었다, 로.postman
그것도 해보세요.에 변경 .proxy
기본값만 설정합니다.
저는 나노를 사용하고 있었고, 이 오류를 알아내는 데 오랜 시간이 걸렸습니다.제 문제는 제가 잘못된 포트를 사용하고 있다는 것이었습니다.5984 대신 5948번 포트를 가지고 있었습니다.
var nano = require('nano')('http://localhost:5984');
var db = nano.use('address');
var app = express();
서버 또는 소켓 연결이 예기치 않게 중단되었을 수 있습니다.
실수로 같은 포트에서 두 개의 애플리케이션을 실행할 때 이 오류가 발생했습니다.next.js 앱과 nest.js에 있는 앱이 있었는데, 포트 8080에서 둘 다 실행되고 있었습니다.env 파일을 보았을 때 .env 파일이 동일한 포트를 가지고 있다는 것을 알았기 때문에 nest.js에서 3000으로 변경했고 모든 것이 작동했습니다.
이것이 오류의 원인이라고 말하는 것이 아니라 가능성이 있습니다.
서비스가 HTTPS에만 게시된 상태에서 HTTP URL에 연결하려고 시도한 경우에도 문제가 발생할 수 있습니다.
분명히 시간이 많이 걸리는 실수입니다!
언급URL : https://stackoverflow.com/questions/16995184/nodejs-what-does-socket-hang-up-actually-mean
'programing' 카테고리의 다른 글
배열 값으로 열을 순차적으로 업데이트 (0) | 2023.06.05 |
---|---|
목록의 각 요소에 정수를 추가하는 방법은 무엇입니까? (0) | 2023.06.05 |
선 끝에 레이블 표시 (0) | 2023.06.05 |
세 개의 열 데이터 프레임을 행렬("긴"에서 "넓은" 형식)로 재구성 (0) | 2023.06.05 |
data.frame을 와이드 형식에서 롱 형식으로 재구성 (0) | 2023.06.05 |