Thread: Request for Comment: Itsa Thin Socket Library!

  1. #16
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> You assume the user is familiar with Win32/Posix/whatever socket API before using this?

    Yes, but remember that the goal here was to simply encapsulate POSIX sockets. That said, I do plan to create an even higher level abstraction at some point, and I intend to use ITSA to do just that. All in good time though...

    >> I didn't see it putting the stream into an error state anywhere, but I could be wrong.

    Yikes, you're right! If the internal send fails then all is well, but if the iostream conversion does then the caller won't know about it. Thanks Elysia!

    >> Well, I disagree. Don't push everything onto users. Make proper and safe public interfaces. Besides, string literals are typically const. People make mistakes, even when reading the manual. Sometimes the compiler can pick the wrong overload, too, and you don't realize it until you run the program. It has happened to me.

    No, I hear you, but I do think you're over-reacting just a bit. If you make Type const then only const data can be passed in, otherwise both are accepted. And I think with a little use you get used to the idea that a single raw pointer as output should be null-terminated. Too presumptuous?

    >> Sure, but it's your job to ensure that the data is sent over the network in a safe way so you can safely read it on the other side. These interfaces are dangerous and I don't like them.

    You're missing the point. There is no concept of "format" to consider here - it's all binary data, period. What conventions you use to process it on either end are what determine "the format", ultimately.

    >> How does it not apply?

    That's rhetorical. Doesn't apply because it's unambiguous.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Sebastiani View Post
    >> You assume the user is familiar with Win32/Posix/whatever socket API before using this?
    Yes, but remember that the goal here was to simply encapsulate POSIX sockets. That said, I do plan to create an even higher level abstraction at some point, and I intend to use ITSA to do just that. All in good time though...
    I see. Well, that's okay.

    >> Well, I disagree. Don't push everything onto users. Make proper and safe public interfaces. Besides, string literals are typically const. People make mistakes, even when reading the manual. Sometimes the compiler can pick the wrong overload, too, and you don't realize it until you run the program. It has happened to me.
    No, I hear you, but I do think you're over-reacting just a bit. If you make Type const then only const data can be passed in, otherwise both are accepted. And I think with a little use you get used to the idea that a single raw pointer as output should be null-terminated. Too presumptuous?
    If we're talking about const char* or const wchar_t*, then I would agree, but as it stands, you're talking about any type.
    Iostreams have an implicit conversion to void*. Surely, it's an error to send an iostream over the network as-is.
    It's just too wide.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #18
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Sorry for somewhat misordering the discussion. I simply didn't see post #8 until now, and I don't know how I missed it.

    I was really just using it for control-flow, but if I do ever decide to throw exceptions from the library that would be the way to go, yes.
    O_o

    You are just using `failure' as cleanup option because you haven't put everything into a component that can successfully cleanup/rollback its own self.

    Placing such primitives into such components is really what I was suggesting.

    Except that allowing the user to supply their own string type is complicated by the fact that the POSIX functions expect canonical C-strings.
    Except that the use of `std::string' I'm referring to is limited to lookup/reverse lookup related to addresses.

    [Edit]
    You have some convenience overloads doing conversion, but I'm not interested in those as the conversion layer is ultimately implemented by the client.
    [/Edit]

    Yes, you'll have more work to do; doing it properly by hiding the conversion is the same thing you are doing at other points in the code, and that work simplifies the look and feel of the code.

    Code:
    wchar_t * s(ReadIPFromUser());
    socket /* whatever */ host(ConvertToANSII(s));
    /* have a socket */
    Code:
    char * s(ReadIPFromUser());
    socket /* whatever */ host(s);
    /* have a socket */
    The examples aren't really bad.

    I'm not saying they are bad.

    I'm just saying that they could be better with not all that much work.

    Code:
    socket /* whatever */ host(ReadIPFromUser());
    /* have a socket */
    The data could be ASCII or UTF-8 or any other format you wish to support.

    If you don't wish to support anything other than ASCII, you could still provide a "hook"--`ConvertUserIPToASCII' for example--called by the templated constructor to allow clients to transparently extend to the support.

    You mean a runtime error check rather than one performed at compile-time, or what?
    No. I am definitely not talking about an error triggered during program execution.

    I am talking about a "firewall" to prevent copying during compile.

    As is, attempting to copy certain objects will force the compiler to complain--somewhat ambiguously for most--about no valid constructor for `managed_socket' despite the fact that the `managed_socket' doesn't appear in the related client code.

    I'm talking about forcing the compiler to make a specific complaint where possible, such as "client objects can not be copied", by conditionally--similarly to the `ITSA_WINSOCK_PLATFORM' configuration macro--using `static_assert'.

    There's nothing wrong with returning boolean values provided that the operations are "atomic" enough.
    I didn't say there was anything wrong with return codes. You are thinking about some other member of this forum.

    I said converting back and forth is an "anti-pattern", and I am completely correct.

    Everywhere you've made those paired conversion could be simplified and implemented without redundancy or falling to the "anti-pattern" with a few helper functions and a few more primitives that "know how to rollback".

    I'd recommend just throwing something useful to the client, but you could definitely use a return value instead.

    Plus forcing users to catch exceptions can make *their* code less manageable as a result.
    That could actually be the case, but you trap an exception locally calling `shutdown'/`reset'/similar for these error conditions.

    You don't have to put the object into such a state, but you are putting the object into such a state.

    A client can't benefit from return codes--as opposed to exceptions--as easily as you imply.

    I, as a client, must check the return value at every point or risk using a silently invalidated object most likely losing valuable error information in the process.

    Code:
    if(server.recv(/*...*))
    {
        if(client.send(/*...*))
        {
            if(server.recv(/*...*))
            {
            }
        }
    }
    (Obviously, that approach is atrocious so more likely I would wrap the conditions into a fail bit as you've internally done.)

    I could just use the object as you've suggested, but I would no way of knowing where an error occurred unless I "watched" for the failure as above.

    If you want to allow for that sort of pattern, you still have more work. You need to provide some sort of stable error code which I can query.

    The internal error code, as currently implemented, is not sufficient. You do not religiously check validity before using underlying components which will result in the underlying error code being updated on many platforms.

    If you make the suggested change by providing a stable error code, you would be allowing for late error propegation/discovery.

    You are correct in saying that some styles of coding benefit from the approach, but I agree with Elysia. I find late discovery to be a waste of time in any language, and I certainly see no reason to try for it in C++.

    I suppose I could just assume std::bad_alloc has been thrown in such an event and use some sort of back-off scheme to mitigate OOM situations.
    You already assume quite a lot about the buffer; I see no reason that one more assumption should cause anyone problems the other assumptions would not already imply.

    Good idea, but just keep in mind that since the data can't be assumed to be contiguous so those reads/writes are going run a bit slower.
    Obviously. I'm talking about a convenience layer.

    You should document the potential for slower throughput.

    Otherwise, I don't see any issue; you said yourself, after a fashion, that you aren't responsible for yahoos not reading the documentation.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. udp socket library
    By Opply in forum C++ Programming
    Replies: 1
    Last Post: 01-29-2014, 07:30 AM
  2. Not able to create 1024 socket request.
    By rahul.shukla in forum Networking/Device Communication
    Replies: 3
    Last Post: 02-15-2010, 03:49 PM
  3. Comment on this socket code
    By mashley in forum C Programming
    Replies: 5
    Last Post: 10-30-2002, 08:31 PM
  4. Fat, normal, thin
    By Series X4 1.0 in forum A Brief History of Cprogramming.com
    Replies: 54
    Last Post: 07-17-2002, 03:53 AM
  5. C++ Socket Library
    By iron in forum C++ Programming
    Replies: 1
    Last Post: 06-28-2002, 09:01 AM