Thread: Socket programming and overloading operators

  1. #1
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401

    Socket programming and overloading operators

    I'm in the middle of programming a socket class for myself, and I've been able to handle most of my problems without major grief. However, now I'm just not sure how to procede.
    I've defined an operator<< for the class so I can send data via the socket much like stream output. The definition looks like this:
    PHP Code:
    void EZWinsock::operator<<(string a)
    {
        
    this->SendData(a);

    SendData has been pretty well tested, so I'm sure it works. Now, whenever I do something like MyWinsock << "Hi", it works. Whenever I try something like MyWinsock << ThisString, it works. But when I try MyWinsock << "hi" << ThisString, it has lots of errors. I'm guessing I need to overload the operator<< again, but I'm not sure how. Any help?
    Thanks.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  2. #2
    Registered User johnnie2's Avatar
    Join Date
    Aug 2001
    Posts
    186
    You'll need to return an EZWinsock object from your operator:

    Code:
    EZWinsock* EZWinsock:: operator<<(string a) {
       this->SendData(a);
       return this;
    }
    That way, in a statement like

    MyWinsock << "hi" << ThisString;

    which is equal to

    ((MyWinsock << "hi") << ThisString);

    the first section to be processed (sending "hi") will return an EZWinsock object, which is then used in the second operation.
    "Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C

  3. #3
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Originally posted by johnnie2
    You'll need to return an EZWinsock object from your operator:
    You are correct, but a reference must be returned, not a pointer.
    Code:
    EZWinsock& EZWinsock:: operator<<(string a) {
       this->SendData(a);
       return *this;
    }
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  4. #4
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Awesome...I thought it'd be something simple like that. Thanks guys.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  5. #5
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    After a prolonged struggle with socket programming, I think I've finally created a workable socket class. After using it for a while, I thought a bit more about the logic of my class. I have the WSAStartup call in the constructor and the WSACleanup call in the destructor. I don't really understand what these functions do; I just read that I need them.
    My main question deals with this segment of code:
    Code:
    int main()
    {
       EZWinsock *a;
       EZWinsock *b;
       a = new EZWinsock();  //constructor for a
       b = new EZWinsock();  //constructor for b
       
       delete a;   //destructor for a
    
       b.Listen();
    
       return 0;
    }
    When a is destroyed, WSACleanup is called. Shouldn't this somehow mess up b's functionality? Will any combination of construction and destruction cause winsock errors because WSACleanup was called?
    Thanks.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  6. #6
    Registered User johnnie2's Avatar
    Join Date
    Aug 2001
    Posts
    186
    Originally posted by pianorain
    When a is destroyed, WSACleanup is called. Shouldn't this somehow mess up b's functionality?
    Yes, Listen() will probably throw back WSANOTINITIALISED since the code attempts to use the Winsock DLL after WSACleanup() has unloaded the DLL from the process' memory space.

    Will any combination of construction and destruction cause winsock errors because WSACleanup was called?
    Yes, keeping such calls in your wrapper constructors and destructors will inevitably lead to problems, as indicated in your code sample. The easiest solution is to move the calls into static member functions:

    Code:
    class EZWinsock {
       static void Init();
       static void Shutdown();
    
       ...
    };
    
    void EZWinsock::Init() {
       WSAStartup(...);
    }
    
    void EZWinsock::Shutdown() {
       WSACleanup();
    }
    Then, explicitly call EZWinsock::Init() before declaring any instances of EZWinsock and explicitly call EZWinsock::Shutdown() after all instances are deleted (or at the end of the main program):

    Code:
    int main(void) {
       EZWinsock *a, *b;
    
       EZWinsock::Init();
    
       a = new EZWinsock;
       b = new EZWinsock;
    
       delete a;
    
       b->Listen();
    
       delete b;
    
       EZWinsock::Shutdown();
    
       return 0;
    }
    Since Init() and Shutdown() are static member functions, they may be called without a specific instance and at any time.

    I don't really understand what these functions do;
    WSAStartup() itself loads the Winsock DLL into the application's memory space and allows your application to begin calling Winsock functions. In addition, an internal reference counter within the DLL is incremented and memory is set aside for use by the DLL for your application's requests (such as the hostent struct that's magically returned from gethostbyaddr() without you having allocated it).

    Conversely, WSACleanup() deallocates this memory, decrements the internal reference counter, and unloads the DLL from your application's memory space.
    Last edited by johnnie2; 02-19-2003 at 11:24 PM.
    "Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C

  7. #7
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Thanks for the info, johnnie2! I didn't know anything about static member functions.
    Right now I have my class designed to throw errors if anything wrong happens. While this makes me use several try/catch blocks, I find it interesting, especially since it is my first time using exception handling. From what I understand, my program should terminate on an unhandled exception. My class will throw an exception if Listen() fails. However, I've run this program and it does wait for a connection. I haven't gotten an unhandled exception error.
    In addition, an internal reference counter within the DLL is incremented.

    WSACleanup()...decrements the internal reference counter
    Does WSACleanup() only unload the DLL if the counter is at 0? That would explain the way it's behaving right now. I can upload my code if you want to try running it for yourself.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  8. #8
    Registered User johnnie2's Avatar
    Join Date
    Aug 2001
    Posts
    186
    Originally posted by pianorain
    Thanks for the info, johnnie2! I didn't know anything about static member functions.
    Glad to help; they come in handy in many places.

    From what I understand, my program should terminate on an unhandled exception. My class will throw an exception if Listen() fails. However, I've run this program and it does wait for a connection.
    Really? Try running the code sample attached to this message. It basically initializes Winsock, creates two sockets, closes one, shuts down Winsock, and attempts to call listen() on the other (with a little error handling at each step). I get error 10093 on the listen() call, which happens to be WSANOTINITIALISED.

    If your program does indeed wait for a connection, you must be calling WSAStartup() more times than WSACleanup(), since...

    Does WSACleanup() only unload the DLL if the counter is at 0?
    is true. If the listen() succeeds, the counter never reached zero.
    "Optimal decisions, once made, do not need to be changed." - Robert Sedgewick, Algorithms in C

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 04-20-2008, 01:15 PM
  2. Class method overloading
    By SevenThunders in forum C++ Programming
    Replies: 20
    Last Post: 03-25-2008, 04:09 AM
  3. Win32/2D DirectX Game Programming Books?
    By Darklighter in forum Game Programming
    Replies: 31
    Last Post: 09-19-2006, 09:40 PM
  4. operator overloading and dynamic memory program
    By jlmac2001 in forum C++ Programming
    Replies: 3
    Last Post: 04-06-2003, 11:51 PM
  5. overloading, L-value and deference operators...
    By AznSftBaLgUrL11 in forum C++ Programming
    Replies: 3
    Last Post: 01-14-2003, 06:49 AM