在客户端closures套接字会导致nodejs服务器崩溃

在C客户端上我这样做:

socket() connect() on port 6969 send() //I have seen that I didn't call recv so nodejs try me to send data but My program was gone and finally closesocket() 

在nodejs服务器上,我收到消息,以便build立连接:

 const port = 6969; var net = require('net'); var server = net.createServer(function(connection) { console.log('client connected'); connection.on('close', function() { console.log('conn closed'); }); connection.on('end', function() { console.log('conn ended');// that is not called }); connection.on("error", function(err) { console.log("Caught flash policy server socket error: "); console.log(err.stack); }); connection.on('data', function(data) { data = data.toString(); console.log('client sended the folowing string:' + data); connection.write("Response"); console.log('Sended response to client'); }); }); server.listen(port, function() { console.log('server is listening'); }); 

这是我的terminal的结果:

 server is listening client connected client sended the folowing string:err404 Sended response to client Caught flash policy server socket error: Error: read ECONNRESET at exports._errnoException (util.js:1018:11) at TCP.onread (net.js:568:26) conn closed 

所以我已经读过节点js ECONNRESET,但我不明白,如果这是正常的,为什么我的nodejs服务器崩溃?

编辑:我发现这个片段:

 connection.on("error", function(err) { console.log("Caught flash policy server socket error: "); console.log(err.stack); }); 

客户端的这个代码会产生相同的错误:

 #ifdef WIN32 Sleep(5000); int iResult = shutdown(sock, SD_BOTH); printf("shutdown is called\n"); Sleep(5000); #elif defined (linux) sleep(5); int iResult = shutdown(sock, SHUT_RDWR); printf("shutdown is called\n"); sleep(5); #endif // WIN32 if (iResult == SOCKET_ERROR) {closesocket(sock);printf("SOCKET_ERROR");} printf("iResult=%d",iResult); 

编辑:现在,我捕捉closures事件和结束事件:但同样的错误仍然抛出。

编辑:我更新了我的代码。 我发现问题在哪里:NodeJs正在尝试向我发送数据,但是我已经调用了shutdown()

有两件事情要考虑,一个在你的服务器上,一个在你的客户端代码中。

服务器代码:

您必须使用end事件而不是close事件,请参阅https://nodejs.org/api/net.html#net_event_end

 connection.on('end', function (){ console.log('client disconnected'); }); 

结束事件:

当套接字的另一端发送一个FIN数据包时发出,从而结束套接字的可读端。

closures事件:

一旦sockets完全closures,发射。 参数had_error是一个布尔值,表示套接字由于传输错误而closures。

这意味着, end事件之后将发生close事件。


客户代码:

您必须在closures套接字之前调用shutdown ,以防止进一步读取或写入,然后由于套接字已经closures而导致错误。

Windows版本的shutdown 在这里MSDN和Linux版本在这里介绍在一个联机帮助页 。

视窗:

 int ret = shutdown(sockfd, SD_BOTH); /* Shutdown both send and receive operations. */ 

Linux的:

 int ret = shutdown(sockfd, SHUT_RDWR); /* Disables further send and receive operations. */ 

刷新发送数据的重要性:

shutdownfunction不保证已经在缓冲区中的数据不会被发送。 所有数据在发生close之前都需要刷新。 在这个答案中写下了一个很好的方式来做到这一点,而不是只睡20毫秒左右。
为了testing这是否是您的问题,您可以在Windows中使用Sleep(2000) ,在Linux中使用Sleep(2000) sleep(2)shutdownclose之间hibernate2秒。


在这个页面上, close/closesocketshutdown之间是一个不错的比较:

您准备好closures套接字描述符上的连接。 这很容易。 你可以使用常规的Unix文件描述符close()函数:

 close(sockfd); 

这将阻止对套接字的更多读取和写入操作。 任何试图在远端读取或写入套接字的人都会收到错误信息。

为了防止对socket的closures有更多的控制,可以使用shutdown()函数。 它允许你切断某个方向的通信,或者两种方式(就像close()一样)简介:

 int shutdown(int sockfd, int how); 

[…]

shutdown()在成功时返回0,错误时返回-1(相应地设置errno)。