【问题标题】:Closing socket in client crashes nodejs server关闭客户端中的套接字会使nodejs服务器崩溃
【发布时间】:2017-12-10 04:21:51
【问题描述】:

在 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 服务器上,我收到消息,因此建立了连接:

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');
});

这是我终端的结果:

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

所以我已经阅读了Node js ECONNRESET,但我不明白这是否正常,为什么我的 nodejs 服务器崩溃了?

编辑:我找到了这个 sn-p:

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);

编辑: 现在我捕获了关闭事件和结束事件:但仍然抛出相同的错误。

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

【问题讨论】:

    标签: c node.js sockets


    【解决方案1】:

    需要考虑两件事,一件在您的服务器中,另一件在您的客户端代码中。

    服务器代码:

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

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

    结束事件:

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

    关闭事件:

    一旦套接字完全关闭就发出。参数 had_error 是一个布尔值,表示套接字是否由于传输错误而关闭。

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


    客户端代码:

    您必须在关闭套接字之前调用shutdown 以防止进一步的读取或写入,这会导致错误,因为套接字已经关闭。

    shutdown 的 Windows 版本被描述为 here at MSDN 和 Linux 变体 here in a manpage

    窗户:

    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. */
    

    刷新发送数据的重要性:

    shutdown 函数不保证缓冲区中已经存在的数据不会被发送。在调用close 之前,需要刷新所有数据。在this answer on SO 中写下了一个很好的方法来做到这一点,而不仅仅是睡眠 20 毫秒左右。
    为了测试这是否是您的问题,您可以在 Windows 中使用 Sleep(2000) 和在 Linux 中使用 sleep(2)shutdownclose 之间休眠 2 秒。


    this page 上是close/closesocketshutdown 之间的一个很好的比较:

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

    close(sockfd); 
    

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

    如果您想更多地控制套接字的关闭方式,您可以使用 shutdown() 函数。它允许你切断某个方向的通信,或者双向切断通信(就像 close() 一样。)概要:

    int shutdown(int sockfd, int how);
    

    [...]

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

    【讨论】:

    • 我使用便携式套接字 #if defined (linux)#define closesocket(s) close(s)#endif 所以在 linux 上我必须调用 shutdown(socket,SHUT_RDWR);
    • @elie:在关机和关闭之间插入 2 秒的睡眠,并告诉我它是否正常工作。您必须确保在关闭之前刷新所有数据。关机只是阻止新数据到来。
    • @elie:你的意思是if (iResult != SOCKET_ERROR) closesocket(sock);而不是if (iResult == SOCKET_ERROR) closesocket(sock);,不是吗?
    • 我有`#define SOCKET_ERROR -1ˋ。我调用shutdown(),如果函数失败(函数返回-1,就像人说的那样)所以我用作后备closesocket()。根据您的回答,我知道只有在关闭成功时才需要调用 closesocket。
    • 好的,我刚刚测试过:我在关闭和关闭套接字之间的发送之间设置了睡眠=> 我看到关闭导致与关闭套接字相同的错误。我有printf("%d",iResult); 并且产生0...所以关闭成功但是对于NodeJs 出了问题。我没有把 == 改成 != 因为这个错误是之前产生的。
    猜你喜欢
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    相关资源
    最近更新 更多