5

On C client I do:

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

On nodejs server I receive the message so the connection is established:

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

This is the result of my 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

So I have read Node js ECONNRESET already but I don't understand if this is normal why my nodejs server crash?

Edit: I found this snippet:

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

This code on client side will produce the same error:

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

Edit: Now I catch either close event and end event: but the same error is still throwed.

Edit: I've Updated my code. And I found where is the problem:NodeJs is trying to send me data but I've already called shutdown().

Et7f3XIV
  • 562
  • 1
  • 7
  • 20

1 Answers1

4

There 2 things to consider, one in your server and one in your client code.

Server code:

You have to use the end event instead of the close event, see https://nodejs.org/api/net.html#net_event_end:

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

end event:

Emitted when the other end of the socket sends a FIN packet, thus ending the readable side of the socket.

close event:

Emitted once the socket is fully closed. The argument had_error is a boolean which says if the socket was closed due to a transmission error.

So that means, that the close event will occur after the end event.


Client code:

You have to call shutdown before closing the socket to prevent further reads or writes which then would cause an error because the socket is already down.

The Windows version of shutdown is described here at MSDN and the Linux variant here in a manpage.

Windows:

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

Importance of flushing sent data:

The shutdown function does not guarantees that data that is already in the buffer does not get send. It is needed that all data get's flushed before the call to close occur. In this answer on SO is written down a nice way to do that rather than just sleep 20 ms or so.
In order to test if that is your problem you can use Sleep(2000) in Windows and sleep(2) in Linux to sleep 2 seconds between shutdown and close.


On this page is a nice comparison between close/closesocket and shutdown:

You're ready to close the connection on your socket descriptor. This is easy. You can just use the regular Unix file descriptor close() function:

close(sockfd); 

This will prevent any more reads and writes to the socket. Anyone attempting to read or write the socket on the remote end will receive an error.

Just in case you want a little more control over how the socket closes, you can use the shutdown() function. It allows you to cut off communication in a certain direction, or both ways (just like close() does.) Synopsis:

int shutdown(int sockfd, int how);

[...]

shutdown() returns 0 on success, and -1 on error (with errno set accordingly.)

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
  • i use portable socket `#if defined (linux)#define closesocket(s) close(s)#endif` so on linux i have to call `shutdown(socket,SHUT_RDWR);` – Et7f3XIV Jul 06 '17 at 09:10
  • @elie: Insert a sleep of 2 seconds between shutdown and close and tell me if it is working. You have to ensure that all data is flushed before closing. Shutdown just prevents new data coming. – Andre Kampling Jul 06 '17 at 10:00
  • 1
    @elie: Also you mean `if (iResult != SOCKET_ERROR) closesocket(sock);` and not `if (iResult == SOCKET_ERROR) closesocket(sock);` aren't you? – Andre Kampling Jul 06 '17 at 11:53
  • I have `#define SOCKET_ERROR -1ˋ. I call shutdown() and if the function fail( the function return -1 like man say) so i use as fallback closesocket(). From your answer I understand I have to call closesocket only if shutdown success. – Et7f3XIV Jul 07 '17 at 00:39
  • Ok, I have tested just right now: I put sleep between send between shutdown and between closesocket=> I saw that shutdown cause the same error as closesocket. I have `printf("%d",iResult);` and that produce 0... So shutdown success but for NodeJs something went wrong. I haven't changed == to != because this error is produce before. – Et7f3XIV Jul 07 '17 at 01:22
  • Now I think I know whats going wrong. You have to use `connection.on('end', function (){ ...` instead of `connection.on('close', function (){ ...`, [see here](https://nodejs.org/api/net.html#net_event_end). The end event get's the FIN packet. – Andre Kampling Jul 07 '17 at 05:55
  • I call recv before shutdown the socket: No error is throw. Is a better solution exists? – Et7f3XIV Jul 07 '17 at 10:13
  • @Et7f3XIV: It was not neccessary to `use` the end event? – Andre Kampling Jul 07 '17 at 11:39
  • Yes it is redundant but i will cleanun some thing when i'm sure that the other side is really logout. – Et7f3XIV Jul 07 '17 at 11:50