Best practice for closing sockets. SO_LINGER or sh

2019-09-06 05:10发布

There is a lot of mixed information out there.

I just want to ensure that the data is fully sent. Should I be doing shutdown/close or close with SO_LINGER and timeout ?

I'm using non-blocking sockets with epoll under Linux and the same code (with defines) under OSX uses kqueue. It would seem SO_LINGER doesn't always work the same on all platforms?

Also when using SO_LINGER on a non-blocking socket, If you get back EWOULDBLOCK do you need to call close again until you don't get EWOULDBLOCK? or can I just ignore the EWOULDBLOCK error from close in that case?

1条回答
家丑人穷心不美
2楼-- · 2019-09-06 05:36

I just want to ensure that the data is fully sent. Should I be doing shutdown/close

Yes, see below.

or close with SO_LINGER and timeout?

I don't find this at all useful, see below.

I'm using non-blocking sockets with epoll under Linux and the same code (with defines) under OSX uses kqueue. It would seem SO_LINGER doesn't always work the same on all platforms?

It should but who knows? There is a large paper on TCP implementation differences, and SO_LINGER isn't mentioned in it as far as I remember. But I'll check later when I can.

Also when using SO_LINGER on a non-blocking socket, If you get back EWOULDBLOCK do you need to call close again until you don't get EWOULDBLOCK? or can I just ignore the EWOULDBLOCK error from close in that case?

Theoretically you should call close() again in obedience to EAGAIN but I'm wondering whether it would actually work. It would make more sense to put the socket into blocking mode for the close, as there is nothing you can select on that will tell you when all the data has been written. But you still have the problem that if the timeout occurs, the socket is closed, the data may be lost, and there is now nothing you can do except log the possibility of a problem.

However back to your problem. The way to assure all data has been written and received before closing is to shutdown the socket for writing at both ends, then issue a read at both ends, which should return end of stream (recv() returns zero), then close the socket. That way you know both peers got to the close at the same time, having already read all the data. If the recv() returns data you have a bug in your application protocol. This should all be carried out in blocking mode in my opinion.

查看更多
登录 后发表回答