I'm connecting a socket asynchronously (O_NONBLOCK + connect). POSIX standard specifies that after socket has been connected is should signal the event by making the file descriptor for the socket ready for writing. It doesn't seem to say anything about failures during async connect.
When testing it on Linux, it seems that sometimes I'm getting POLLOUT and sometimes POLLERR in this situation. Is there any pattern in the behaviour? Can I make it report the errors in a single way? Does POSIX say something I have overlooked?
D. J. Bernstein has some stuff that looks like it might be relevant: http://cr.yp.to/docs/connect.html. In particular he suggests several different ways to get errors out.
The UNIX Socket FAQ has a section on Connect with timeout, that includes getting the error from a failed connection using getsockopt
Related
I have a node.js process which has several entry points, including a tcp server, websocket server, and named pipe server. I am wondering if any interactions with these connections will be blocking.
Example: for a given connection, if there isnt anything in the buffer because the client didnt send anything yet, will this block all other code from running in the Node.js process until the client sends data?
My understanding is that node will offload I/O operations like these to the system kernel, so it wouldnt hold up the call stack.
Most likely I am getting something wrong here so please let me know! Thank you.
This is a very interesting question!
I would recommend you to start by understanding what the event loop is (reading https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/) and then understanding the difference between blocking & non-blocking calls (reading https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/).
Now we'll know a bit more about how node works behind the scenes, what blocking and non-blocking operations are and therefore we're equipped to understand and spot what will or won't block our loop.
Will a TCP connection block it? There may be a module out there that will, it really depends on each case, library, implementation.
Regarding TCP on the "native" implementation, if you're using the node.js Net module you'll find that it is a:
module [that] provides an asynchronous network API for creating stream-based TCP or IPC servers
Therefore, in principle, it will be non-blocking.
As an example, if we look at the socket.write documentation itself, we'll find that this function:
Returns true if the entire data was flushed successfully to the kernel buffer. Returns false if all or part of the data was queued in user memory. 'drain' will be emitted when the buffer is again free.
Therefore it should not block.
PS: Another interesting article on this subject is https://medium.com/#hnasr/when-nodejs-i-o-blocks-327f8a36fbd4
Happy reading, and keep an eye out for blocking function calls!
I had hard time debugging a problem with my NodeJS' code today.
I have problems when I open two connections to the same unix socket (reasons though); and for unknown reasons, sometimes it works fine throughout; and sometimes I don't get back any data, but connect is fired for only one of them.
I'm still trying to debug, but I deep dived into documentation and faced another question. As NodeJS Docs (12.x LTS) states: (about net.Socket)
# Event: 'connect'
Added in: v0.1.90
Emitted when a socket connection is successfully established. See net.createConnection().
# Event: 'ready'
Added in: v9.11.0
Emitted when a socket is ready to be used. Triggered immediately after 'connect'.
(https://nodejs.org/docs/latest-v12.x/api/net.html)
I wondered if that is where I should look for error:
what does immediately mean? Does it mean synchronously? If so, is there any difference between ready and connect?
is there any point for one using ready instead of connect for doing after-connection-established/opened tasks?
what is the difference between the two?
Thanks!
This event is emitted from net for consistency across different APIs. See the original commit here:
https://github.com/nodejs/node/commit/1c8149417a5dec9b2af056f306822b8a22a09706
It was created to make developers' life easier when working with fs and net code, so that they don't have to remember all the intricate details of a given stream implementation.
In practice, the Node.js socket code does this:
self.emit('connect');
self.emit('ready');
I use net.connect to make socket connection, I wonder how to detect it when a connection has failed?
It seems this doesn't work
//this will return a net.Socket and automatically connect
var client = net.connect({port:22000, host:'10.123.9.163'});
//doesn't trigger a error event even if connection fails
client.on('error', (err)=>{console.log('something wrong')});
//now an error event is emitted reasonably
client.write('hello');
when I run this piece of code, the connection should fail, and it indeed fails because when I write some data, an error occurs. But, I can not detect the connection failure. How can I do that?
=====Ready to close======
God damn it, I think I have just make a mistake. In fact the connection succeeded but due to some security strategy the server close the connection, I find out by doing a telnet. After trying other port which should definitely fail, the error event is emitted, everything go normal as expected. So, I am gonna close this question in case of misleading other people, and also thank you guys for helping me :)
The easiest and most portable way is to simply implement a 'ping-pong' check where both sides send some kind of 'ping' request every so often. If n outstanding ping requests go unanswered after some period of time, then consider the connection dead. This kind of algorithm is basically what OpenSSH uses for example (although it's not enabled by default).
Is there something like
remote_client.close()
or
request.close()
for closing the http.createClient connection?
It seems like in some occasions, the socket connection is still hanging there after the "response" event is emitted and properly handled.
Upgrade to the latest version of node.js (0.4.8).
The syntax for creating clients has changed. You now have
http.request
Which returns a ClientRequest which you can .end and it gives you a ClientResponse in the callback.
The ClientReponse is just a Readable Stream and you can .destroy a stream
Except for certain rare and extraordinary circumstances, your connections are performing correctly and will close by themselves, (or more precisely, will be closed automatically by your computer operating system's TCP stack.)
The issue you are seeing is that the socket underlying the connection will only be closed once all of its data have been delivered and acknowledged, and after the TIME_WAIT period has expired. This is well defined and perfectly normal behavior.
For an explanation of why this is required, see
UNIX Socket FAQ» 2.7 - Please explain the TIME_WAIT state
TCP Tutorial
But the bottom line is: don't worry about sockets; they're your operating system's responsibility.
Context: Linux (Ubuntu), C, ZeroMQ
I have a server which listens on ipc:// SUB ZeroMQ socket (which physically is a Unix domain socket).
I have a client which should connect to the socket, publish its message and disconnect.
The problem: If server is killed (or otherwise dies unnaturally), socket file stays in place. If client attempts to connect to this stale socket, it blocks in zmq_term().
I need to prevent client from blocking if server is not there, but guarantee delivery if server is alive but busy.
Assume that I can not track server lifetime by some external magic (e.g. by checking a PID file).
Any hints?
Non-portable solution seems to be to read /proc/net/unix and search there for a socket name.
Without showing your code all of this is guesswork... that said...
If you have a PUB/SUB pair, the PUB will hang around to make sure that its message gets through. Perhaps you're not using the right type of zmq pair. Sounds more like you have a REP/REQ pair instead.
This way, once you connect from the client (the REQ side), you can do a zmq_poll to determine if the socket is available for writing. If yes, then go ahead with your write, otherwise shutdown the client and handle the error condition (if it is an error in your system).
Maybe you can try to connect to the socket first, with your own native socket. If the connection succeeds, it's quite high possibility your publisher could work fine.
There is another solution. Don't use ipc:// sockets. Instead use something like tcp://127.0.0.101:10001. On most UNIXes that will be almost as fast as IPC because the OS recognizes that it is a local connection and shortcuts the full IP stack processing.