fpagliughi / sockpp

Modern C++ socket library.
BSD 3-Clause "New" or "Revised" License
782 stars 126 forks source link

Scatter/gather I/O (like readv/writev) #26

Closed snej closed 1 year ago

snej commented 4 years ago

For performance reasons it's good to be able to read or write multiple discontiguous byte ranges in one system call. The generic system calls for this are writev and readv; the socket-specific ones are sendmsg and recvmsg.

The C++ methods for these would probably take a const std::vector<iovec>& parameter.

fpagliughi commented 4 years ago

I started this for Linux and hadn't even looked to see if there was a portable API for Windows or if I would need to fake it. I will look into sendmsg and recvmsg.

I was also wondering what to do about short returns... if the call didn't transfer all the requested data in or out. Keeping with the philosophy of the thin wrapper, the basic call should do this. But could/should we come up with an equivalent to readn() & writen() for scatter gather (keep retrying until done).

It's a tough call, since a retry would break the atomic promise of the base call. (At least that's how it works in Linux).

fpagliughi commented 4 years ago

This is coming along, but the implementation seems to require a bit too much ugly boilerplate. Doing an output for a payload, header, and footer (as strings) looks something like this:

std::string str { "This is a test" };

const std::string HEADER { "<start>" },
                  FOOTER { "<end>" };

std::vector<iovec> outv {
    iovec { (void*) HEADER.data(), HEADER.length() },
    iovec { (void*) str.data(), str.length() },
    iovec { (void*) FOOTER.data(), FOOTER.length() }
};

ssock.write(outv);

It may be worth putting together an iovec_collection class, or something like that. It would just be able to construct the vector of iovec objects without thr ugly, manual build, like:

iovec_collection outv { HEADER, str, FOOTER };
ssock.write(outv);