Socket reusing with boost asio - sockets

I try to use a boost asio socket, bound to a local address/port combination. That works great. What doesn't work, is the re-using of the socket once the socket and application has been stopped and restarted.
//
// open the socket - it would also be opened by the async_connect()
// method but we might need an open socket to bind it
_socket.open(boost::asio::ip::tcp::v4());
if ( _bindLocal ) {
boost::asio::socket_base::reuse_address option(true);
_socket.set_option(option);
_socket.bind( _localEndpoint );
}
// Invoke async. connect. Immediate return, no throw.
_socket.async_connect(_remoteEndpoint,
boost::bind(&MyTransceiver::handleConnect, this,
boost::asio::placeholders::error));
What am I missing? Is the ordering of the open(), set_option() and bind() call correct?

The code looks fine. Try to use error_code to get the result of your set_option() call.
boost::system::error_code ec;
_socket.set_option(boost::asio::socket_base::reuse_address(true), ec);

Related

Epoll events for connecting sockets

I create epoll and register some non-blocking sockets which try connect to closed ports on localhost. Why epoll tells me, that i can write to this socket (it give event for one of created socket with eventmask contain EPOLLOUT)? But this socket doesn't open and if i try send something to it i get an error Connection refused.
Another question - what does mean even EPOLLHUP? I thought that this is event for refused connection. But how in this case event can have simultaneously EPOLLHUP and EPOLLOUT events?
Sample code on Python:
import socket
import select
poll = select.epoll()
fd_to_sock = {}
for i in range(1, 3):
s = socket.socket()
s.setblocking(0)
s.connect_ex(('localhost', i))
poll.register(s, select.EPOLLOUT)
fd_to_sock[s.fileno()] = s
print(poll.poll(0.1))
# prints '[(4, 28), (5, 28)]'
All that poll guarantees is that your application won't block after calling corresponding function. So you are getting what you've paid for - you can now rest assured writing to this socket won't block - and it didn't block, did it?
Poll never guarantees that corresponding operation will succeed.
poll/select/epoll return when the file descriptor is "ready" but that just means that the operation will not block (not that you will necessarily be able to write to it successfully).
Likewise for EPOLLIN: for example, it will return ready when a socket is closed; in that case, you won't actually be able to read data from it.
EPOLLHUP means that there was a "hang up" on the connection. That would really only occur once you actually had a connection. Also, the documentation (http://linux.die.net/man/2/epoll_ctl) says that you don't need to include it anyway:
EPOLLHUP
Hang up happened on the associated file descriptor. epoll_wait(2) will always wait for this event; it is not necessary to set it in events.

Asio: 'Address Already In Use' on Bind, yet I can still Connect

I'm having what doesn't seem to be a problem but I don't understand the error. Basically, I've been trying to work on code that "gracefully" shuts down a tcp socket on both ends. At the end of my program, on both sides, I shutdown my sockets before closing them. On a quick restart, which is the thing I'm trying to solve, the much worse problem of crashing because the sockets are lingering on both sides doesn't happen anymore. The shutdown/then close seems to work on that front.
However, i get "Address already in use" still, which usually made it so that I couldn't connect. Now I'm able to connect after that error just fine. I've read a lot on the subject of graceful shutdown, reuse address, and the like. And I guess my question is, how, if the socket error'd on bind ("Address already in use"), after a successful open, is it possibly able to connect to the endpoint? In other words, if the address is actually already in use, how is the connection being made? Also, of note, reuse address doesn't work in this situation. Because I'm using the same socket settings, local/remote addresses and ip.
Failing to bind() the socket to an address does not invalidate the underlying socket. As such, the connect() operation will continue with an unbound socket, deferring to the kernel to bind to a local endpoint.
Here is a complete example demonstrating this behavior:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
// This example is not interested in all handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}
int main()
{
using boost::asio::ip::tcp;
// Create all I/O objects.
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, {tcp::v4(), 0});
tcp::socket server(io_service, tcp::v4());
// Open socket1, binding to a random port.
tcp::socket socket1(io_service, {boost::asio::ip::address_v4::any(), 0});
tcp::socket socket2(io_service); // non-open
// Explicitly open client2, which will bind it to the any address.
boost::system::error_code error;
socket2.open(tcp::v4(), error);
assert(!error);
assert(socket2.local_endpoint().port() == 0);
// Attempt to bind socket2 to socket1's address will fail with
// an already in use error, leaving socket2 bound to the any endpoint.
// (e.g. a failed bind does not have side effects on the socket)
socket2.bind(socket1.local_endpoint(), error);
assert(error == boost::asio::error::address_in_use);
assert(socket2.local_endpoint().port() == 0);
// Connect will defer to the kernel to bind the socket.
acceptor.async_accept(server, boost::bind(&noop));
socket2.async_connect(acceptor.local_endpoint(),
[&error](const boost::system::error_code& ec) { error = ec; });
io_service.run();
io_service.reset();
assert(!error);
assert(socket2.local_endpoint().port() != 0);
}

OpenSSL Nonblocking Socket Accept And Connect Failed

Here is my question:
Is it bad to set socket to nonblocking before I call accept or connect? or it should be using blocking accept and connect, then change the socket to nonblocking?
I'm new to OpenSSL and not very experienced with network programming. My problem here is I'm trying to use OpenSSL with a nonblocking socket network to add security. When I call SSL_accept on server side and SSL_connect on client side, and check return error code using
SSL_get_error(m_ssl, n);
char error[65535];
ERR_error_string_n(ERR_get_error(), error, 65535);
the return code from SSL_get_error indicates SSL_ERROR_WANT_READ, while ERR_error_string_n prints out "error:00000000:lib(0):func(0):reason(0)", which I think it means no error. SSL_ERROR_WANT_READ means I need to retry both SSL_accept and SSL_connect.
Then I use a loop to retry those function, but this just leads to a infinite loop :(
I believe I have initialized SSL properly, here is the code
//CRYPTO_malloc_init();
SSL_library_init();
const SSL_METHOD *method;
// load & register all cryptos, etc.
OpenSSL_add_all_algorithms();
// load all error messages
SSL_load_error_strings();
if (server) {
// create new server-method instance
method = SSLv23_server_method();
}
else {
// create new client-method instance
method = SSLv23_client_method();
}
// create new context from method
m_ctx = SSL_CTX_new(method);
if (m_ctx == NULL) {
throwError(-1);
}
If there is any part I haven't mentioned but you think it could be the problem, please let me know.
SSL_ERROR_WANT_READ means I need to retry both SSL_accept and SSL_connect.
Yes, but this is not the full story.
You should retry the call only after the socket gets readable, e.g. you need to use select or poll or similar functions to wait, until the socket gets readable. Same applies to SSL_ERROR_WANT_WRITE, but here you have to wait for the socket to get writable.
If you just retry without waiting it will probably eventually succeed, but only after having 100s of failed calls. While doing select does not guarantee that it will succeed immediately at the next call it will take only a few calls of SSL_connect/SSL_accept until it succeeds and it will not busy loop and eat CPU in the mean time.

WSASocket programming, how to hold on the non-blocking connect() function till some time point?

I have a problem in the WSASocket programming. I want to do some trick at server side so that
it could hold the client side wait for a while in the WSAWaitForEvents() function waiting for
FD_CONNECT event.
Details are as follows:
At the client side, the socket is non-blocking mode. And it tries to connect to the server. It main code is something like:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
WSAEvent hEvent = WSACreateEvent();
WSAEventSelect(s, hEvent, FD_CONNECT); //this also make socket non-blocking mode.
connect(s, &someserveraddr, sizeof(someserveraddr)); //connect to some server in non-block mode
WSAWaitForMultipleEvents(1, &hEvent, TRUE, WSA_INFINITE, FALSE); //this will block until success or faile
At the server side, one the server sees a connection from that client, it will do something special which will also take sometime, for example: calling doSomethingLengthy(), So I want to hold the client side blocking at function WSAWaitForMultipleEvents(...) until the server finishes that task. But I don't know how to achieve this. Usually, the server code would like:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(s, &someaddress, sizeof(someaddress));
listen(s, 5);
SOCKET acceptSocket = accept(s, &someotheraddress, sizeof(someotheraddress));
The problem is that, I don't know where/when to call doSomethingLengthy(). I know that once listen() is done, the client will be notified done and WSAWaitForMultipleEvents() will return. But I cannot call doSomethingLengthy() before listen() otherwise the client side connect() will fail.
You can't. The server end of connect happens before the server gets to see the accepted socket, via the backlog queue.
FD_CONNECT tells you when the socket has connected, but FD_WRITE tells you when you are allowed to send data over the connection. So try waiting for FD_WRITE instead (do note that you can get FD_WRITE multiple times during a connection's lifetime, but you will always get it after a successful connect() in addition to FD_CONNECT).

Time Gap Between Socket Calls ie. Accept() and recv/send calls

I am implementing a server in which i listen for the client to connect using the accept socket call.
After the accept happens and I receive the socket, i wait for around 10-15 seconds before making the first recv/send call.
The send calls to the client fails with errno = 32 i.e broken pipe.
Since i don't control the client, i have set socket option *SO_KEEPALIVE* in the accepted socket.
const int keepAlive = 1;
acceptsock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_length)
if (setsockopt( acceptsock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)) < 0 )
{
print(" SO_KEEPALIVE fails");
}
Could anyone please tell what may be going wrong here and how can we prevent the client socket from closing ?
NOTE
One thing that i want to add here is that if there is no time gap or less than 5 seconds between the accept and send/recv calls, the client server communication occurs as expected.
connect(2) and send(2) are two separate system calls the client makes. The first initiates TCP three-way handshake, the second actually queues application data for transmission.
On the server side though, you can start send(2)-ing data to the connected socket immediately after successful accept(2) (i.e. don't forget to check acceptsock against -1).
After the accept happens and I receive the socket, i wait for around 10-15 seconds before making the first recv/send call.
Why? Do you mean that the client takes that long to send the data? or that you just futz around in the server for 10-15s between accept() and recv(), and if so why?
The send calls to the client fails with errno = 32 i.e broken pipe.
So the client has closed the connection.
Since I don't control the client, i have set socket option SO_KEEPALIVE in the accepted socket.
That won't stop the client closing the connection.
Could anyone please tell what may be going wrong here
The client is closing the connection.
and how can we prevent the client socket from closing ?
You can't.