在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服务器崩溃这是正常的呢?
编辑:我找到了这个代码段:
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()
。
答案 0 :(得分:4)
需要考虑两件事,一件在服务器中,另一件在客户端代码中。
服务器代码:
您必须使用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
以防止进一步的读取或写入,这会因为套接字已经关闭而导致错误。
Windows版shutdown
描述为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)
在shutdown
和close
之间休息2秒。
在this page上对close/closesocket
和shutdown
进行了很好的比较:
您已准备好关闭套接字描述符上的连接。这很简单。你可以使用常规的Unix文件描述符close()函数:
close(sockfd);
这将阻止对套接字的任何更多读写操作。任何试图在远程端读取或写入套接字的人都会收到错误。
如果您想要更多地控制套接字关闭的方式,可以使用shutdown()函数。它允许你切断某个方向或两个方向的通信(就像close()一样。)故事梗概:
int shutdown(int sockfd, int how);
[...]
shutdown()成功时返回0,错误时返回-1(相应地设置errno。)