What is the scope of a SOCKET object in Winsock? - c++

The title pretty much says it all. I'm new to Winsock, and I need to know what the scope of a SOCKET object is.
Do I need to worry about it going out of scope when using it in a class member variable (since when it's returned, it's not dynamic memory)?
Thanks.
I'm pretty sure the answer to this is no, but since I can't find the info, I figured I would put it out there, for quick reference to others in the future.

The MSDN documentation for socket says the following:
When a session has been completed, a closesocket must be performed.
And the accompanying sample does just that. The documentation for closesocket is more forceful:
An application should always have a matching call to closesocket for each successful call to socket to return any socket resources to the system.
So as long as you keep the SOCKET descriptor somewhere you can use it until you call closesocket. You could consider putting it inside your own RAII type (or use an existing one) to avoid leaks. If you "forget" the descriptor, you will leak the internal resources.

Internally, SOCKET is just some ID, which is refers to some internal Windows structure. You can work with it like with HANDLE or with usual pointer.
I.e. nothing will happen, if it will go out of scope (but it can leak resources, like HANDLE, if you forgot CloseHandle), if you copy it - you will go 2 same sockets, which are referring to same Windows structure, etc.

Related

How to encapsulate C/C++ socket send and receive functions in a class?

I'm using the standard C/C++ socket function, but I'd like to encapsulate them into a C++ class. The problem is that the functions for sending and receive returns (or require) pointers to void. Is there any way to use an object that encapsulates those values?
For example, in Java the Socket class uses both ObjectOutputStream and ObjectInputStream in order to work with Object type so every object can be sent via Sockets.
I know that in Java the approach is quite different because the pointers are hidden to the programmer, but is there any similar solution in C++?
socket isn't a c++ function. It's a system level function and it doesn't know anything about objects (or indeed anything in c++), so you have to arrange to provide it with a pointer to the data you want transferred.
As #GCT says, socket isn't a function but is a system level function which is used to handle network connections. In C/C++ each socket is identified with an Integer value, so it's not easy, as you want, to handle it as an object.
I recommend you to read this tutorial to know more about socket.
Maybe it can help you: I have a project that show how to use sockets in C++. Server and client are contained in their own class. You can get it by this link.

Does DuplicateHandle() do any interprocess communication (IPC) and if not why target params?

I am finding DuplicateHandle() very confusing. The third and fourth params, hTargetProcessHandle and lpTargetHandle seem to imply that this API function does some form of interprocess communication, but what I have been reading online seems to imply (without saying directly) that in fact this function cannot communicate with anything outside of the address space of its own process and that if you really do want to say copy the local process handle to another process you have to do that yourself manually.
So can someone please please take pity on me and tell me definitively whether or not this function does any IPC itself? Also if it doesn't do any IPC then what is the point of those two parameters? How can there be a 'target' if no data is sent and the output of this function is not visible to other processes?
At first I thought I could call GetCurrentProcess() and then use DuplicateHandle() to copy the local process handle to another process, but then I started to realize that it probably isn't that easy.
The third parameter hTargetProcessHandle is documented as
A handle to the process that is to receive the duplicated handle.
That means that the handle (which is just a numeric value underneath) will become usable within the target process. However, how you get this handle into the target process and in what context it is to be used there is out of the scope of that function. Also note that "is to receive" points in the future and it refers to the result of the call, so it must be after the call has finished.
As an analogy, you want to allow a friend in your house. For that, you are creating a second key to your door. Just that doesn't mean that your friend can now unlock your door, because you first have to give it to them, but it's a first step.

What does boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::shutdown() do?

The extensive documentation helpfully says:
This function is used to shut down SSL on the stream. The function call will block until SSL has been shut down or an error occurs.
Which leaves me with these questions:
Does this close the actual connection too?
If not, how do I do that?
Can I reuse the stream by calling boost::asio::connect(theSocket.lowest_layer(), ... again?
Under the covers, asio calls SSL_Shutdown() in the underlying OpenSSL library:
The documentation for which is here:
https://www.openssl.org/docs/manmaster/ssl/SSL_shutdown.html
... and contains the following ominous text:
The behaviour of SSL_shutdown() additionally depends on the underlying BIO.
However, my understanding of things is that the ssl::stream object is not a socket (by design) but more like a protocol layer that sits on top of a Stream-like object. Thus the asio::ssl layer has no knowledge of its next_layer() other than that it must support the free functions read,write, async_read and async_write. Certainly no knowledge about whether the layer supports the concept of shutdown() (or even close()).
Therefore I would expect the underlying socket, given by lowest_layer() to still be open when shutdown() returns. Furthermore, I would expect that shutdown() will not have been called on the lowest_layer(). You'll want to do this after ssl::shutdown returns, or in the handler passed to ssl::async_shutdown

Functions responsibility on data in C

Recently I ran into a problem at work where you have two functions; one opens a file descriptor (which is a local variable in the function), and passes it to another function where it is used for reading or writing. Now, when one of the operations read/write fails the function that was doing the read/write closes this file descriptor, and returns.
The question is, whose responsibility is to close the file descriptor, or let's say do cleanup:
the function which created the fd
the function which experienced the error while read/write
Is there a design rule for these kind of cases; let's say creation and cleanup.
BTW, the problem was that both functions attempted to close the fd, which resulted in a crash on the second call to close.
There are two parts to this answer — the general design issue and the detailed mechanics for your situation.
General Design
Handling resources such as file descriptors correctly, and making sure they are released correctly, is an important design issue. There are multiple ways to manage the problem that work. There are some others that don't.
Your tags use C and C++; be aware that C++ has extra mechanisms available to it.
In C++, the RAII — Resource Acquisition Is Initialization — idiom is a great help. When you acquire a resource, you ensure that whatever acquires the resource initializes a value that will be properly destructed and will release the resource when destructed.
In both languages, it is generally best if the function responsible for allocating the resource also releases it. If a function opens a file, it should close it. If a function is given an open file, it should not close the file.
In the comments, I wrote:
Generally, the function that opened the file should close it; the function that experienced the error should report the error, but not close the file. However, you can work it how you like as long as the contract is documented and enforced — the calling code needs to know when the called code closed the file to avoid double closes.
It would generally be a bad design for the called function to close the file sometimes (on error), but not other times (no error). If you must go that way, then it is crucial that the calling function is informed that the file is closed; the called function must return an error indication that tells the calling code that the file is no longer valid and should neither be used nor closed. As long as the information is relayed and handled, there isn't a problem — but the functions are harder to use.
Note that if a function is designed to return an opened resource (it is a function that's responsible for opening a file and making it available to the function that called it), then the responsibility for closing the file falls on the code that calls the opening function. That is a legitimate design; you just have to make sure that there is a function that knows how to close it, and that the calling code does close it.
Similar comments apply to memory allocation. If a function allocates memory, you must know when the memory will be freed, and ensure that it is freed. If it was allocated for the purposes of the current function and functions it calls, then the memory should be released before return. If it was allocated for use by the calling functions, then the responsibility for release transfers to the calling functions.
Detailed mechanics
Are you sure you're using file descriptors and not FILE * (file streams)? It's unlikely that closing a file descriptor twice would cause a crash (error, yes, but not a crash). OTOH, calling fclose() on an already closed file stream could cause problems.
In general, in C, you pass file descriptors, which a small integers, by value, so there isn't a way to tell the calling function that the file descriptor is no longer valid. In C++, you could pass them by reference, though it is not conventional to do so. Similarly with FILE *; they're most usually passed by value, not by reference, so there isn't a way to tell the calling code that the file is not usable any more by modifying the value passed to the function.
You can invalidate a file descriptor by setting it to -1; that is never a valid file descriptor. Using 0 is a bad idea; it is equivalent to using standard input. You can invalidate a file stream by setting it to 0 (aka NULL). Passing the null pointer to functions that try to use the file stream will tend to cause crashes. Passing an invalid file descriptor typically won't cause crashes — the calls may fail with EBADF set in errno, but that's the limit of the damage, usually.
Using file descriptors, you will seldom get a crash because the file descriptor is no longer valid. Using file streams, all sorts of things can go wrong if you try using an invalid file stream pointer.

Is closesocket thread safe?

Is it safe if I want to call closesocket() on a server socket from 1 thread which is separate from another thread which runs the server using the same server socket?
The call itself is thread-safe, but the practice is not. Whenever you're deallocating a resource whose identifier could be reused after it's deallocated, you must synchronize with all threads that could possibly use it. Otherwise, it's possible that, after the resource is deallocated, a new resource (in your case, socket) could be allocated with the same identifier (socket number), and code intending to access the (now closed) server socket could end up operating on a different socket.
The degree to which this is dangerous (and whether it can happen at all) depends a lot on your code. It might not happen if you never create any more sockets after closing the server socket. But it's still conceptually very wrong, and anyone competent reviewing your code would consider this very bad.
Edit: The solution to problems like this is protection of the resource descriptor (not the resource itself) with a reader-writer lock (rwlock). Accessing the resource descriptor (the integer variable holding the socket number, in your case) requires holding a "read" lock on it, whether you'll be performing input or output or other operating using the resource it refers to. Deallocating the resource (and storing a sentinel value like -1 in the variable holding the descriptor) requires a write lock.
Yes, it's not a problem. Naturally, there will be exceptions/errors generated in the other thread/s that have calls outstanding on the socket, but the network stack itself, (which has to be thread-safe because of all the different processes/threads that are normally using it), will not be damaged.