I'm about to develop some sockets related stuff in C++ and would like the software to be as portable between Windows and Linux as possible right from the start (making it portable later is tricky.)
I've looked at different libraries, there is one for C++ from alhem.net and of course there is boost::asio. boost::asio looks very promising but would be a very big dependency for applications this small.
Is it even worth writing the stuff myself or should I just use a library? If I do it myself what would be the main pitfalls?
I've developed a few portable wrappers around sockets. Make sure you don't go down the crappy lane of no return that is constituted of WinSock2 events. Other than that, as I see it, the biggest differences are:
to start networking in Windows, you need to call ::WSAStartup(), to shut it down in Windows, run ::WSACleanup(); in Linux do nothing,
close() in Linux is closesocket() in Windows,
default buffer sizes differ between both drivers and operating systems, so make sure to set them using SO_RCVBUF and SO_SNDBUF,
SO_REUSEADDR steals the address on Windows, allows frequent re-opening on Linux; you'd probably only want to use this flag in Linux,
making a socket non-blocking uses ::ioctlsocket() in Windows, ::fcntl() in Linux,
the header files are different, <sys/socket.h> and friends in Linux, <WinSock.h> in Windows,
to go portable, the easiest way is probably to use ::select() to wait for data to arrive,
fd_sets are totally different on Windows/Linux; this is only relevant if you need to optimize initialization of fd_sets, such as when adding/removing arbitrary sockets,
in Windows, any thread hanging on the socket is released with an error code when the socket is closed, in Linux the thread remains waiting. If the thread is blocking the socket with for instance ::recvfrom(), you might consider using ::sendto() to release the stalling thread under Linux.
Everything else I ever needed just worked out of the låda.
Winsocks aren't very compatible with Posix sockets:
In Winsocks a socket is of type SOCKET. On Posix it's simply a file descriptor (int), on which you can perform normal read() and write() calls.
They don't return errors the same way.
They don't support some options on recv() and send().
You have to initialize and unitialize the Winsocks library with two specials functions.
I don't think you can close Windows sockets with shutdown() or close(). It's something like closesocket() instead.
There must be more differences, but that's what I can remember right now. If you want portability with Winsocks, you'll have a small library for closing a socket, printing an error message and so on.
I'd probably go with boost::asio, personnally (I've never used it, though).
Take a look at the "Adaptive Communications Environment" (ACE) library:
(ACE Home Page)
It provides some nice abstractions and a lot of flexibility all rolled up in a portable library that supports Windows, MacOS and Linux.
It has a bit of a steep learning curve, but I got very good value from it.
How much socket stuff will you be using? I've done several apps where the socket stuff was pretty high level (open, read, write), and worked perfectly from Windows to Linux. If it's more than that - go with boost.
Honestly, I'd use boost::asio as a first preference. If you really want to get down and dirty with the sockets API, you can use the standard BSD-style sockets API on both Windows and Linux - it's just that on Windows you'll have to link to (and initialize) Winsock2, whereas on Linux you won't have a separate library to link against.
Have a look at this... http://sourceforge.net/projects/cpp-sockets/
Related
In bare outlines, I've got an application which looks through the directories at startup and creates special files' index - after that it works like daemon. The other application creates such 'special' files and places them in some directory. What way of informing the first application about a new file (to index it) is the most common, simple (the first one is run-time, so it shouldn't slow it too much), and cross-platform if it is possible?
I've looked through RPC and IPC but they are too heavy (also non-cross-platform and slow (need a lot of features to work - I need a simple light well-working way), probably).
Pipes would be one option: see Network Programming with Pipes and Remote Procedure Calls (Windows) or Creating Pipes in C (Unix).
I haven't done this in a while but from my experience with RPC, DCOM, COM, .NET Remoting, and socket programming, I think pipes is the most straightforward and efficient option.
For windows (NTFS) you can get notification from OS that directory was changed. But it is not crosspl. and not about two apps.
"IPC but them are too heavy" - no no, they are not heavy at all. You should look at named pipes - this IPC is fastest and it is in both Win/Unix-like with slight differences. Or sockets!
eisbaw suggested TCP. I'd say, to make it even more simple, use UDP.
Create a listening thread that will receive packets, and handle it from there - on all applications.
Since it is on the same PC you'll never lose any packet, something that UDP could mistakenly do when on network.
Each application instance will need a special port but this is easy to configure with configuration files that you (I assume) already have.
Keep it simple (:
Local TCP sockets are guarenteed to work - as already mentioned by Andrey
Shared memory would be another option, take a look at
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2044.html
As Andrey noted, if you agree on the full path ahead of time, you can just have the OS tell you when it's added. All major platforms actually support this in some form. You can use a cross-platform library for this, such as QFileSystemWatcher.
EDIT: I don't think QFileSystemWatcher will cause too much of a performance hit. It definitely relies on the underlying OS for notifications on Linux, FreeBSD, and Mac OS (and I think Windows). See http://qtnode.net/wiki/QFileSystemWatcher
memory mapped files, socket, and named pipes are all highly efficient, cross platform, ipc mechanisms. Well, the apis to access named pipes and memory mapped files differ between POSIX and Win32, but the basic mechanisims are similar enough that its easy to make a cross platform wrapper. Sockets and named pipes tend to be fast because, in inter-process situations, the OS developers (of most common OSs) have built in shortcuts that essentially makes the socket / named pipe write a rather simple wrap of a memory section.
I'm doing some fairly simple cross-platform TCP socket programming. I have unfortunately found out that when compiled on Windows, my sockets are non-blocking by default, while on OS X they are blocking by default. How do I force a socket into blocking mode on Windows? Do they normally default to non-blocking mode or is something terribly wrong?
My code is based in part on these simple examples:
http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoClient.c
http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoServer.c
No, plain old BSD style sockets are not non-blocking by default on Windows. See the examples in the Winsock Programmer's FAQ.
If you use MFC and its CAsyncSocket mess, then yes, it's all non-blocking, but that's a separate issue.
I believe this reference may help; note, in particular, that
Although blocking operations on
sockets are supported under Windows
Sockets, their use is strongly
discouraged. Programmers who are
constrained to use blocking mode --
for example, as part of an existing
application which is to be ported --
should be aware of the semantics of
blocking operations in Windows
Sockets.
If you're fully aware of the zillion issues listed here, and find dealing with all of them preferable to designing your program to fit in well with Windows rather than being a half-beeped port from Unix, go right ahead with a ioctlsocket call with the cmd argument set to FIONBIO and the third argument pointing to a longword worth 0. But, don't say you weren't warned;-).
i'm using this example implementation found at http://tangentsoft.net/wskfaq/examples/basics/select-server.html
This is doing most of what I need, handles connections without blocking and does all work in its thread (not creating a new thread for each connection as some examples do), but i'm worried since i've been told winsock will only support max 64 client connectios :S
Is this 64 connections true?
What other choices do I have? It would be cool to have a c++ example for a similar implementation.
Thanks
Alternative library:
You should consider using boost asio. It is a cross platform networking library which simplifies many of the tasks you may have to do.
You can find the example source code you seek here.
About the 64 limit:
There is no hard 64 connection limit that you will experience with a good design. Basically if you use some kind of threading model you will not experience this limitation.
Here's some information on the limit you heard about:
4.9 - What are the "64 sockets" limitations?
There are two 64-socket limitations:
The Win32 event mechanism (e.g.
WaitForMultipleObjects()) can only
wait on 64 event objects at a time.
Winsock 2 provides the
WSAEventSelect() function which lets
you use Win32's event mechanism to
wait for events on sockets. Because it
uses Win32's event mechanism, you can
only wait for events on 64 sockets at
a time. If you want to wait on more
than 64 Winsock event objects at a
time, you need to use multiple
threads, each waiting on no more than
64 of the sockets.
The select() function is also limited
in certain situations to waiting on 64
sockets at a time. The FD_SETSIZE
constant defined in winsock.h
determines the size of the fd_set
structures you pass to select(). It's
defined by default to 64. You can
define this constant to a higher value
before you #include winsock.h, and
this will override the default value.
Unfortunately, at least one
non-Microsoft Winsock stack and some
Layered Service Providers assume the
default of 64; they will ignore
sockets beyond the 64th in larger
fd_sets.
You can write a test program to try
this on the systems you plan on
supporting, to see if they are not
limited. If they are, you can get
around this with threads, just as you
would with event objects.
Source
#Brian:
if ((gConnections.size() + 1) > 64) {
// For the background on this check, see
// www.tangentsoft.net/wskfaq/advanced.html#64sockets
// The +1 is to account for the listener socket.
cout << "WARNING: More than 63 client "
"connections accepted. This will not "
"work reliably on some Winsock "
"stacks!" << endl;
}
To the OP:
Why would you not want to use winsock2?
You could try to look at building your own server using IOCP, although making this cross-platform is a little tricky. You could look at Boost::asio like Brian suggested.
Before you decide that you need 'alternatives to winsock2" please read this: Network Programming for Microsoft Windows.
In summary, you DON'T need an 'alternative to Winsock2' you need to understand how to use the programming models supplied to full effect on the platform that you're targeting. Then, if you really need cross platform sockets code that uses async I/O then look at ASIO, but, if you don't really need cross platform code then consider something that actually focuses on the problems that you might have on the platform that you do need to focus on - i.e. something windows specific. Go back to the book mentioned above and take a look at the various options you have.
The most performant and scalable option is to use IO Completion Ports. I have some free code available from here that makes it pretty easy to write a server that scales and performs well on a windows (NT) based platform; the linked page also links to some articles that I've written about this. A comparison of my framework to ASIO can be found here: http://www.lenholgate.com/blog/2008/09/how-does-the-socket-server-framework-compare-to-boostasio.html.
I've recently bumped into something called IOCP on the windows platform, to be more precise: Input/Output Control Ports. This seems to be the most efficient way to code your server software when it needs to hold thousands of users concurrently.
(Correct me if I'm wrong, but thread-per-socket, polling, and asynchronous callbacks (thread on every callback) are not efficient enough.)
I am wondering if there are any 3rd party libraries available that implement this concept. I know the win32 api supplies us with CreateIoCompletionPort, FreeBSD has kqueue and linux in general can use /dev/epoll that works somewhat similarly... But isn't there a crossplatform library (such as boost::thread) that handles this stuff for me?
Have you looked at boost::asio?
I'm not sure if it has all this functionality yet, but I believe that's one of the things it's intended for.
I know this is a late reply to this thread, but for those interested in a x-platform library supporting async IO on both Linux/UNIX and Windows, you might want to take a look at libuv.
libuv was initially constructed as the foundational underpinnings of node.js, but it has evolved to become a powerful abstraction library for many low-level, x-platform concerns including async IO, non-blocking TCP sockets & named pipes, UDP, timers, child process spawning
, high resolution time, thread pool scheduling, etc.
libevent works on a number of *nix OSes and also runs on Windows.
I've noticed that boost.asio has a lot of examples involving sockets, serial ports, and all sorts of non-file examples. Google hasn't really turned up a lot for me that mentions if asio is a good or valid approach for doing asynchronous file i/o.
I've got gobs of data i'd like to write to disk asynchronously. This can be done with native overlapped io in Windows (my platform), but I'd prefer to have a platform independent solution.
I'm curious if
boost.asio has any kind of file support
boost.asio file support is mature enough for everyday file i/o
Will file support ever be added? Whats the outlook for this?
Has boost.asio any kind of file support?
Starting with (I think) Boost 1.36 (which contains Asio 1.2.0) you can use [boost::asio::]windows::stream_handle or windows::random_access_handle to wrap a HANDLE and perform asynchronous read and write methods on it that use the OVERLAPPED structure internally.
User Lazin also mentions boost::asio::windows::random_access_handle that can be used for async operations (e.g. named pipes, but also files).
Is boost.asio file support mature enough for everyday file i/o?
As Boost.Asio in itself is widely used by now, and the implementation uses overlapped IO internally, I would say yes.
Will file support ever be added? Whats the outlook for this?
As there's no roadmap found on the Asio website, I would say that there will be no new additions to Boost.Asio for this feature. Although there's always the chance of contributors adding code and classes to Boost.Asio. Maybe you can even contribute the missing parts yourself! :-)
boost::asio file i/o on Linux
On Linux, asio uses the epoll mechanism to detect if a socket/file descriptor is ready for reading/writing. If you attempt to use vanilla asio on a regular file on Linux you'll get an "operation not permitted" exception because epoll does not support regular files on Linux.
The workaround is to configure asio to use the select mechanism on Linux. You can do this by defining BOOST_ASIO_DISABLE_EPOLL. The trade-off here being select tends to be slower than epoll if you're working with a large number of open sockets. Open a file regularly using open() and then pass the file descriptor to a boost::asio::posix::stream_descriptor.
boost::asio file i/o on Windows
On Windows you can use boost::asio::windows::object_handle to wrap a Handle that was created from a file operation. See example.
boost::asio::windows::random_access_handle is the easiest way to do this, if you need something advanced, for example asynchronous LockFileEx or something else, you might extend asio, add your own asynchronous events. example
io_uring has changed everything.
asio now support async file read/write.
See the releases notes:
asio 1.21.0 releases notes
ASIO supports overlapped I/O on Windows where support is good. On Unixes this idea has stagnated due to:
Files are often located on the same physical device, accessing them sequentially is preferable.
File requests often complete very rapidly because they are physically closeby.
Files are often critical to complete the basic operation of a program (e.g. reading in its configuration file must be done before initializing further)
The one common exception is serving files directly to sockets. This is such a common special-case that Linux has a kernel function that handles this for you. Again, negating the reason to use asynchronous file I/O.
In Short: ASIO appears to reflect the underlying OS design philosophy, overlapped I/O being ignored by most Unix developers, so it is not supported on that platform.
Asio 1.21 appears to have added built-in filesystem support.
For instance, asio::stream_file now exists with all the async methods you'd expect.
Linux has an asio Library that is no harder to use than Windows APIs for this job (I've used it). Both sets of operating systems implement the same conceptual architecture. They differ in details that are relevant to writing a good library, but not to the point that you cannot have a common interface for both OS platforms (I've used one).
Basically, all flavors of Async File I/O follow the "Fry Cook" architecture. Here's what I mean in the context of a Read op: I (processing thread) go up to a fast food counter (OS) and ask for a cheeseburger (some data). It gives me a copy of my order ticket (some data structure) and issues a ticket in the back to the cook (the Kernel & file system) to cook my burger. I then go sit down or read my phone (do other work). Later, somebody announces that my burger is ready (a signal to the processing thread) and I collect my food (the read buffer).