Thread: Setting up server for game - initialization is skipped by 'goto'

  1. #1
    Registered User
    Join Date
    May 2012
    Posts
    28

    Setting up server for game - initialization is skipped by 'goto'

    WinClient.cpplinkerfile.hSecondary.cppWinServer.cpp

    Hi, I'm currently altering the following tutorial files for my own use (Tidy Tutorials: Windows C++ Socket Example Using Client Server and Multi-Threading) using VC++ 2010 Express.

    I've got them to run as the tutorial shows fine, and went ahead and changed a couple of things. Everything works so far, but the next thing I'd like to do is get the message sent from the client (char buffer, I believe) to be changed into a string and communicated to another function, called secondaryCommand(), so that I can work with it further and incorporate it into the game. I can get WinServer.cpp to send basic integers to secondaryCommand(), but I can't get it to send the string it receives from the client I haven't eaten for 5 hours just trying to fix this, so I hope someone here knows what's going on.

    Here's the error I'm getting:
    Code:
    1>  WinServer.cpp
    1>  WinServer.cpp(152): error C2362: initialization of 'sString' is skipped by 'goto FINISH'
    1>          WinServer.cpp(140) : see declaration of 'sString'
    1>          WinServer.cpp(152) : see declaration of 'FINISH'
    Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped

    Here's all of my code. Sorry it's kind of long. There are 3 pieces (Linkerfile.h, Secondary.cpp, and WinServer.cpp). I've highlighted the area in WinServer.cpp that's giving me a compiler error in blue.
    I also attached all of the files to the top of this, including WinClient (if you'd like to try it out yourself and see).

    Linkerfile.h
    Code:
    #ifndef LINKERFILE_H
    #define LINKERFILE_H#include <string>
    using namespace std;
    int secondaryCommand(string sString);
    #endif
    Secondary.cpp
    Code:
    // Used as a middleman from the game to Winserver.cpp
    #include "linkerfile.h"
    #include <string>
    #include <fstream>
    #include <istream>
    #include <iostream>
    using namespace std;
    int secondaryCommand(string sString)
    {
     cout << "If you see WORKS! below then it works." << endl; // actually it won't say "WORKS!" it'll just show the buffer
     cout << sString << endl; 
     return 0;
    }
    WinServer.cpp
    Code:
    #include <winsock2.h>
    #include <windows.h>
    #include <fcntl.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <stdio.h>
    #include <string>
    #include "linkerfile.h"
    DWORD WINAPI SocketHandler(void*);
    int serverPasswordCheck()
    {
     char serverPass[256],
              *guess = "pass\n"; // Change the password here
        puts("Enter your password: " );
         while(fgets(serverPass, 256, stdin) != NULL )
         {
           if(strcmp(serverPass, guess) == 0 )
           {
              puts("Password is correct. Initializing server.");
        break;
           }
           else
           {
              puts( "Password is incorrect. Please try again.");
           }
         }
      return 0;
    }
    int welcomeMessage()
    {
     static int x = 1;
     if(int x = 1)
     { printf("This is the server program for Leujor RPG.\n"); }
     x--;
     serverPasswordCheck(); // checks a password before going back to main()
     return 0;
    }
    int main(int argv, char** argc){
     //Runs only once
     welcomeMessage();
     //The port you want the server to listen on
     int host_port= 1101;
     //Initialize socket support WINDOWS ONLY!
     unsigned short wVersionRequested;
     WSADATA wsaData;
     int err;
     wVersionRequested = MAKEWORD( 2, 2 );
      err = WSAStartup( wVersionRequested, &wsaData );
     if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
          HIBYTE( wsaData.wVersion ) != 2 )) {
         fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
      goto FINISH;
     }
     //Initialize sockets and set any options
     int hsock;
     int * p_int ;
     hsock = socket(AF_INET, SOCK_STREAM, 0);
     if(hsock == -1){
      printf("Error initializing socket %d\n",WSAGetLastError());
      goto FINISH;
     }
     
     p_int = (int*)malloc(sizeof(int));
     *p_int = 1;
     if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
      (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
      printf("Error setting options %d\n", WSAGetLastError());
      free(p_int);
      goto FINISH;
     }
     free(p_int);
     //Bind and listen
     struct sockaddr_in my_addr;
     my_addr.sin_family = AF_INET ;
     my_addr.sin_port = htons(host_port);
     
     memset(&(my_addr.sin_zero), 0, 8);
     my_addr.sin_addr.s_addr = INADDR_ANY ;
     
     if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
      fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
      goto FINISH;
     }
     if(listen( hsock, 10) == -1 ){
      fprintf(stderr, "Error listening %d\n",WSAGetLastError());
      goto FINISH;
     }
     
     //Now lets go to the server stuff
     int* csock;
     sockaddr_in sadr;
     int addr_size = sizeof(SOCKADDR);
     
     while(true){
      printf("*Ready to receive more players*\n");
      csock = (int*)malloc(sizeof(int));
      
      if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
       printf("Received connection from %s \n",inet_ntoa(sadr.sin_addr));
       CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
      }
      else{
       fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
      }
     }
    FINISH:
    ;
    }
    DWORD WINAPI SocketHandler(void* lp)
    {
        int *csock = (int*)lp;
     char buffer[1024];
     int buffer_len = 1024;
     int bytecount;
     memset(buffer, 0, buffer_len);
     if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
      fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
      goto FINISH;
     }
     printf("From username: \"%s\"\n", buffer); // this will display their username soon
     std::string sString = buffer;
      
     // Send the data to another .cpp file (Secondary.cpp)
     secondaryCommand(sString);
     strcat_s(buffer, " SERVER ECHO");
     if((bytecount = send(*csock, buffer, strlen(buffer), 0))==SOCKET_ERROR){
      fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
      goto FINISH;
     }
     
    FINISH:
     free(csock);
        return 0;
    }
    Note: you'll need to add Ws2_32.lib for it to work, although I'm pretty sure you already know that. Sorry I'm pretty new to C++ and this is my first attempt at networking a program with a purpose. Thank you so much for helping (or just reading even).
    Last edited by Pikmeir; 05-02-2012 at 12:00 AM.

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Your code will actually be just fine if you eliminate every goto from your program, and never use one ever again...

    Whether one believes that there is never a good reason to use a goto, or thinks that there are a few situations where they are acceptable, I think people will agree that from the looks of it you've become so reliant on them that you just cant write anything significant without them. That's a really bad place to be in. It's like being unable to afford insulation in your house because you have nothing left after paying the heating costs.

    In my opinion, you need to decide to make a firm commitment that your practice of abundantly using gotos is history, and that from now on you will only even consider using a goto as a last resort, when even 1 hour of searching for alternatives cannot provide anything better. And that's for every time you even think of using one.
    Without actually being there like a personal trainer to make sure you stick to such a goal, I can only hope that you succeed. Perhaps a goto jar (like a swear jar) would help.

    This probably isn't the kind of answer you were expecting, but I am very much being serious here.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Wow, not only is using goto a horrible idea. But using several goto-labels with the same name must be the epitome of poor coding. I tip my hat to you sir, you have reached unheard of levels of spaghetti code.

    Have you by any chance had any "prior exposure to BASIC" ?
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    the link you posted is giving you horrible advice. abandon that tutorial immediately and find a different one.

    goto is an absolutely horrible (but sometimes necessary) part of the C++ language. this is not one of those situations where it is even marginally acceptable, and its use is NEVER encouraged.

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    28
    The gotos were there originally from the tutorial link, and I left them because the program worked fine. When I added a few lines of code (the blue part) it suddenly decided it didn't want to compile anymore, which confused me since everything worked fine before. I know gotos are usually a bad idea, I was just confused why my program stopped working when I didn't think I altered anything that could mess with a goto.

    As per iMalc's advice, I removed the gotos in the bottom section (the only section I've tampered with) and suddenly the code works!
    Didn't think the solution would be so simple. I've never used gotos before, and now I definitely never will.
    Thank you~

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    remove every use of goto. in main() you can replace every occurrence with return 0;

    for SocketHandler(), you should use new instead of malloc to allocate space for the socket descriptor in main(), then after you pass it to SocketHandler(), you can use a std::unique_ptr<int> to wrap around the descriptor, which will automatically free it when the function returns. you can then replace all occurrences of goto in SocketHandler() with return 0;

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Pikmeir View Post
    The gotos were there originally from the tutorial link, and I left them because the program worked fine. When I added a few lines of code (the blue part) it suddenly decided it didn't want to compile anymore, which confused me since everything worked fine before. I know gotos are usually a bad idea, I was just confused why my program stopped working when I didn't think I altered anything that could mess with a goto.

    As per iMalc's advice, I removed the gotos in the bottom section (the only section I've tampered with) and suddenly the code works!
    Didn't think the solution would be so simple. I've never used gotos before, and now I definitely never will.
    Thank you~
    Oh that's a huge relief. Sorry I misjudged the situation.

    Actually, now you mention it, I do recall finding an example about networking on Microsoft's site which used several gotos. I think my advice need to go to them instead.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    28
    @Elkvis I'm glad to hear that simply replacing the gotos with 'return 0;' in main() would be the way to go. I got it working by doing that myself (after iMalc suggested to remove the gotos), but I wasn't confident it would be the best way so thanks for letting me know I wasn't wrong.
    As for the other function with goto, I'm not confident I can easily switch malloc to new (I have almost no experience in regular C), but I'll try to look up some info on the internet so I can finally remove the remaining gotos with return 0s later. Thanks again for your help.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    new is really simple.

    instead of the C way
    Code:
    int* some_int_pointer = (int*)malloc(sizeof(int));
    do this instead
    Code:
    int* some_int_pointer = new int;
    then to release the memory, instead of
    Code:
    free(some_int_pointer);
    you would say
    Code:
    delete some_int_pointer;
    this is just a very simple example, but it represents the C++ way of handling dynamic memory, as opposed to the C way.

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    28
    Oh wow, that's clearly much simpler in C++. Thank you for the explanation too~! I'll be sure to put those in my code instead.

  11. #11
    Registered User
    Join Date
    Sep 2007
    Posts
    131
    Quote Originally Posted by iMalc View Post
    Your code will actually be just fine if you eliminate every goto from your program, and never use one ever again...
    I don't agree with this, but I will add that using a goto should be the absolute last resort when nothing else will work. I think I've used a goto once, ever.

  12. #12
    Registered User
    Join Date
    May 2012
    Posts
    28
    I went ahead and replaced malloc and free with new and delete, and the code runs perfectly fine (Thank you!!!). Now I can send buffer to Secondary.cpp and manipulate it (this is where my entire program will do its work, using the client's inputs and spitting out the results it should display back to the client's screen over the network). I haven't removed the gotos from the top section yet, since I'm not messing with the top yet, but I will as soon as I get this next small issue fixed (which is probably my last issue before I can start mixing in the game).

    But now I'm having a new problem trying to get sString to be returned back to WinServer.cpp to be sent as buffer to go to the client program - I tried setting sString (a new string variable I made with Secondary.cpp) as a global string, and also tried converting sString to a char before sending it over, but in the end I can't get it to send.

    This is the code area where I'd like sString to go into --> strcat_s(buffer, " <-- message from Server");
    [I highlighted the area in my code in blue below]

    Here's the code now: (Sorry this is so long)

    Secondary.cpp

    Code:
    // Used as a middleman from Winserver.cpp to the game
    #include "linkerfile.h"
    #include <string>
    #include <fstream>
    #include <istream>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>using namespace std;
    int secondaryCommand(string sString)
    {
     cout << sString << endl; // just a temporary code to check and see if the Server can manipulate the data
     sString = "If you see this message on the client, then everything works!";
    return 0;
    }
    Linkerfile.h is the same as above.

    WinServer.cpp
    Code:
    #include <winsock2.h>
    #include <windows.h>
    #include <fcntl.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <stdio.h>
    #include <string>
    #include "linkerfile.h"
    DWORD WINAPI SocketHandler(void*);
    int serverPasswordCheck()
    {
     char serverPass[256],
              *guess = "pass\n"; // Change the password here
        puts("Enter your password: " );
         while(fgets(serverPass, 256, stdin) != NULL )
         {
           if(strcmp(serverPass, guess) == 0 )
           {
              puts("Password is correct. Initializing server.");
        break;
           }
           else
           {
              puts( "Password is incorrect. Please try again.");
           }
         }
      return 0;
    }
    int welcomeMessage()
    {
     static int x = 1;
     if(int x = 1)
     { printf("This is the server program for Leujor RPG.\n"); }
     x--;
     serverPasswordCheck(); // checks a password before going back to main()
     return 0;
    }
    int main(int argv, char** argc){
     welcomeMessage();
     int host_port= 1101; //The port you want the server to listen on
    
     //Initialize socket support (Windows only)
     unsigned short wVersionRequested;
     WSADATA wsaData;
     int err;
     wVersionRequested = MAKEWORD( 2, 2 );
      err = WSAStartup( wVersionRequested, &wsaData );
     if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
          HIBYTE( wsaData.wVersion ) != 2 )) {
         fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
      goto FINISH;
     }
    
     //Initialize sockets and set any options
     int hsock;
     int * p_int ;
     hsock = socket(AF_INET, SOCK_STREAM, 0);
     if(hsock == -1){
      printf("Error initializing socket %d\n",WSAGetLastError());
      goto FINISH;
     }
     
     p_int = new int;
     *p_int = 1;
     if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
      (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
      printf("Error setting options %d\n", WSAGetLastError());
      delete p_int;
      goto FINISH;
     }
     delete p_int;
    
     //Bind and listen
     struct sockaddr_in my_addr;
     my_addr.sin_family = AF_INET ;
     my_addr.sin_port = htons(host_port);
     
     memset(&(my_addr.sin_zero), 0, 8);
     my_addr.sin_addr.s_addr = INADDR_ANY ;
     
     if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
      fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
      goto FINISH;
     }
     if(listen( hsock, 10) == -1 ){
      fprintf(stderr, "Error listening %d\n",WSAGetLastError());
      goto FINISH;
     }
     
     //Server stuff 
     int* csock;
     sockaddr_in sadr;
     int addr_size = sizeof(SOCKADDR);
     
     while(true){
      printf("*Ready to receive more players*\n");
      csock = new int;
      
      if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
       printf("Received connection from %s \n",inet_ntoa(sadr.sin_addr));
       CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
      }
      else{
       fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
      }
     }
    FINISH:
    ;
    }
    DWORD WINAPI SocketHandler(void* lp)
    {
     int *csock = (int*)lp;
     char buffer[1024];
     int buffer_len = 1024;
     int bytecount;
     memset(buffer, 0, buffer_len);
     if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
      fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
      return 0;
     }
     printf("From username: \"%s\"\n", buffer); // this will display their username later
     
    std::string sString = buffer;
      
     // Send the data to Secondary.cpp
     secondaryCommand(sString);
    
     // Send the data back to the Client
     strcat_s(buffer, " <--- DOES IT WORK?");
      if((bytecount = send(*csock, buffer, strlen(buffer), 0))==SOCKET_ERROR){
      fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
      return 0;
     }
    delete csock;
    return 0;
    }
    Last edited by Pikmeir; 05-02-2012 at 06:39 PM.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by iMalc
    Actually, now you mention it, I do recall finding an example about networking on Microsoft's site which used several gotos. I think my advice need to go to them instead.
    Looking at the implementation of SocketHandler, it seems that the idiom of using goto to jump to the clean up code was used. However, this was badly done in welcomeMessage, and then of course since this is C++, there was no need for this idiom in the first place since there is exception handling.

    EDIT:
    Quote Originally Posted by Pikmeir
    As per iMalc's advice, I removed the gotos in the bottom section (the only section I've tampered with) and suddenly the code works!
    Unfortunately, by just removing the goto in SocketHandler without also duplicating the free(csock) and later the delete csock, you fail to clean up in one case. The goto in SocketHandler was a problem because you created a variable in the middle of the block, yet in terms of achieving the goal of keeping clean up code at the end of the function, the goto was fine. A better solution for this in C++ is to use a smart pointer or a container that can clean up after itself.
    Last edited by laserlight; 05-02-2012 at 08:28 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    May 2012
    Posts
    28
    I understand gotos aren't evil, but I see how they can easily screw everything up in a program. Either way, I'd much rather have a solid programs so I'll make sure I never start using gotos.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Pikmeir
    But now I'm having a new problem trying to get sString to be returned back to WinServer.cpp to be sent as buffer to go to the client program - I tried setting sString (a new string variable I made with Secondary.cpp) as a global string, and also tried converting sString to a char before sending it over, but in the end I can't get it to send.
    How does it not work?

    I suggest that you stick to std::string, and then use its c_str() member function when you need a null terminated C-style string from it. Also, note that in your secondaryCommand function (what a useless name!), you assign to sString, but sString a parameter that will be destroyed immediately afterwards. Perhaps you intended to pass by reference?

    Quote Originally Posted by Pikmeir
    I understand gotos aren't evil, but I see how they can easily screw everything up in a program. Either way, I'd much rather have a solid programs so I'll make sure I never start using gotos.
    Then why do you still have goto in your program? I mean, I shake my head when I see that you incorrectly removed the use of goto when it had some value, but left the uses of goto when it provides no value over return statements (other than the notion of a single exit, which is kind of bogus in the face of possible exceptions anyway).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Setting up server socket?
    By aprop in forum Networking/Device Communication
    Replies: 1
    Last Post: 07-20-2010, 06:40 PM
  2. facing problems in setting up NFS server/client
    By kris.c in forum Tech Board
    Replies: 0
    Last Post: 12-19-2006, 10:12 PM
  3. Setting up 2D game (VIEW)
    By Deo in forum Game Programming
    Replies: 9
    Last Post: 06-08-2005, 03:54 PM
  4. Give me some opinions on setting up a server
    By Shadow in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 04-19-2004, 10:38 AM
  5. Your favourite fantasy game setting?
    By fry in forum Game Programming
    Replies: 4
    Last Post: 10-16-2002, 06:26 AM