-3

I have the following C++ program that uses socket programming for a battleship game and it is written on window. But i need it to run on ubuntu. Please assist to advice. How do i proceed to implement the code, i know for ubuntu, the socket programming part will be different from window.

Coding:Server

            //Battleship Server
            #include <iostream>     //For basic I/O operations
            #include <conio.h>      //For _getch(); to pause the program
            #include <winsock2.h>   //For network operations
            #include <windows.h>    //Needed by winsock
            #include <ws2tcpip.h>   //Used for and addrinfo related functions
            #include <time.h>       //For rand()
            #define BUFLEN 64       //Default buffer length
            #define PORT "3490"     //Port to be used 

            #pragma warning(push)
            #pragma warning(disable:4996)

            using namespace std;

            //Global ship names and corresponding letters
            char *Shipnames[5] = {
                "Aircraft Carrier",
                "BattleShip",
                "Destroyer",
                "Submarine",
                "patrol Boat",
            };

            char Letter[5] = { 'A', 'B', 'D', 'S', 'P' };

            struct Ship
            {
                //To keep track of hits
                char Hitbox[5];

                //X & Y positions
                int X;
                int Y;

                //Length of ship
                int len;

                //Direction
                //true = vertical (Y)
                //false = horizontal (X)
                bool Direction;
            };

            //Translates letter cords to numbers
            //eg: A5 = 15, B7 = 27, E3 = 53
            int TransLettoNumb(char *Cord)
            {
                char Letters[8] = {
                    'A',
                    'B',
                    'C',
                    'D',
                    'E',
                    'F',
                    'G',
                    'H',
                };

                char Lowercase[8] = {
                    'a',
                    'b',
                    'c',
                    'd',
                    'e',
                    'f',
                    'g',
                    'h',
                };

                //Check through upper case
                for (int x = 0; x < 8; x++)
                {
                    if (Cord[0] == Letters[x])
                        return x + 1;
                }

                //check through lower case
                for (int x = 0; x < 8; x++)
                {
                    if (Cord[0] == Lowercase[x])
                        return x + 1;
                }

                return 0;
            }

            bool sendl(int sockfd, bool hit)
            {
                char *Line = new char[BUFLEN];

                if (hit)
                {
                    Line = "Hit!";
                }
                else
                {
                    Line = "Miss!";
                    cout << "Miss!" << endl;
                }

                bool var = true;

                if (send(sockfd, Line, strlen(Line), 0) == SOCKET_ERROR)
                    var = false;

                return var;
            }

            //For checking if the client hit a boat
            bool Checkhit(Ship ships[], char Cord[], int sockfd)
            {
                //Translate cords to ints
                int Ycord = (Cord[1] - 48);
                int Xcord = TransLettoNumb(Cord);

                //Length of ship
                int Len;

                //For each ship
                for (int n = 0; n < 4; n++)
                {
                    //Set length
                    if (n == 0)
                        Len = 5;
                    else if (n == 1)
                        Len = 4;
                    else if (n == 2)
                        Len = 3;
                    else if (n == 3)
                        Len = 3;
                    else if (n == 4)
                        Len = 2;

                        //loop through the hitbox
                        for (int i = 0; i < Len; i++)
                        {
                            //If the x cord equals the ships cords plus hitbox (i), test y cords
                            if (Xcord == (ships[n].X + i))
                            {
                                //loop through the hitbox
                                for (int i = 0; i < Len; i++)
                                {
                                    //If the y cord equals the ships cords plus hitbox (i)
                                    if (Ycord == (ships[n].X + i))
                                    {
                                        //the ship was hit, update the hitbox
                                        ships[n].Hitbox[i] = 'X';
                                        {                           
                                            cout << Shipnames[n] << " was hit!"<< endl;

                                            //send hit
                                            sendl(sockfd, true);

                                            //Send which ship was hit
                                            send(sockfd, Shipnames[n], strlen(Shipnames[n]), 0);

                                            return true;
                                        }
                    }
                    }
                    }
                    }
                    }

                //The ship was not hit
                return false;
            }

            void PlaceShips(Ship ships[])
            {
                int randnumb;

                //For each ship
                for (int n = 0; n < 5; n++)
                {
                    //Randomize direction
                    randnumb = rand() % 2;

                    if (randnumb == 1)
                        ships[n].Direction = true;
                    else
                        ships[n].Direction = false;

                    do
                    {
                        randnumb = 0;

                        //randomize x
                        ships[n].X = rand() % 8 + 1;

                        //randomize y
                        ships[n].Y = rand() % 8 + 1;

                        //If direction is true, check y 
                        if (ships[n].Direction)
                        {
                            //If the ship hit the wall
                            if ((ships[n].Y + ships[n].len) > 8)
                                randnumb = 1;
                        }
                        else //else check x
                        {
                            //If the ship hit the wall
                            if ((ships[n].X + ships[n].len) > 8)
                                randnumb = 1;
                        }

                    } while (randnumb > 0);
                }
            }

            int main()
            {
                //Quit flag
                bool quit = false;

                //Initialize random seed
                srand(time(NULL));

                //Declare ships
                Ship ships[5];

                //Initialize ship lengths
                ships[1].len = 5;
                ships[2].len = 4;
                ships[3].len = 3;
                ships[4].len = 3;
                ships[5].len = 2;

                //Hit counter
                int HitCounter = 0;

                //Declare some winsock variables
                int status;                                 //To keep track of errors
                WSADATA wsaData;                            //For winsock initialization
                SOCKET ListenSocket = INVALID_SOCKET;       //Socket for listening on
                SOCKET ClientSocket = INVALID_SOCKET;       //Socket for communicating with client
                struct addrinfo *result = NULL;             //struct to hold address information
                struct addrinfo address;                    //struct to hold connection information
                char recvbuf[BUFLEN];                       //Buffer for receiving information
                char sendbuf[BUFLEN];                       //Buffer for sending

                // Initialize Winsock
                status = WSAStartup(MAKEWORD(2, 2), &wsaData);
                if (status != 0) 
                {
                    cout << "failed to initialize winsock" << endl;
                    _getch();
                    return 1;
                }

                ZeroMemory(&address, sizeof(address));
                address.ai_family = AF_INET;
                address.ai_socktype = SOCK_STREAM;
                address.ai_protocol = IPPROTO_TCP;
                address.ai_flags = AI_PASSIVE;

                //Get IP and port info
                status = getaddrinfo(NULL, PORT, &address, &result);
                if (status != 0)
                {
                    cout << "getaddrinfo failed with error: " << WSAGetLastError() << endl;
                    freeaddrinfo(result);
                    _getch();
                    return 1;
                }

                //Create a socket for listening
                ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
                if (ListenSocket == INVALID_SOCKET)
                {
                    cout << "failed to create socket with error: " << WSAGetLastError() << endl;
                    freeaddrinfo(result);
                    _getch();
                    return 1;
                }

                //Bind to the port
                status = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
                if (status == SOCKET_ERROR)
                {
                    cout << "failed with error " << WSAGetLastError() << " binding to port " << PORT << endl;
                    freeaddrinfo(result);
                    _getch();
                    return 1;
                }
                else cout << "binded to port " << PORT << endl;

                //Done with the results
                freeaddrinfo(result);

                //Server loop
                while (quit == false)
                {
                    //Listening for client connections
                    //5 is the amount of clients that can wait on queue
                    status = listen(ListenSocket, 5);
                    if (status == SOCKET_ERROR)
                    {
                        cout << "listen() failed with error: " << WSAGetLastError() << endl;
                        closesocket(ListenSocket);
                        WSACleanup();
                        _getch();
                        return 0;
                    }

                    //Accept client connection
                    ClientSocket = accept(ListenSocket, NULL, NULL);
                    if (ClientSocket == INVALID_SOCKET)
                    {
                        cout << "accept failed with error: " << WSAGetLastError() << endl;
                        closesocket(ClientSocket);
                        WSACleanup();
                        _getch();
                        return 1;
                    }
                    else cout << "connection accepted from client" << endl;

                    //set up game...

                    int cord;

                    //Initialize ship hitboxes
                    for (int x = 0; x <5; x++)
                    {
                        //Initialize hitbox
                        for (int i = 0; i<5; i++)
                            ships[x].Hitbox[i] = Letter[x];
                    }


                    //Randomize ship locations
                    PlaceShips(ships);

                    status = 1;

                    //Game loop
                    while (status > 0)
                    {
                        ///Receive client's bomb cords
                        status = recv(ClientSocket, recvbuf, BUFLEN, 0);

                        cout << endl << "client bombed square " << recvbuf[0] << recvbuf[1] << endl;

                        //Check if it was a hit or miss and reply to client
                        if (!Checkhit(ships, recvbuf, ClientSocket))
                            sendl(ClientSocket, false);
                        else
                            HitCounter++;

                        status = 0;

                        //generate random cord
                        do
                        {
                            cord = rand() % 8;

                            if (cord >= 0 && cord < 9)
                                sendbuf[0] = (cord + 65);
                            else
                                status = 1;

                            cord = rand() % 8;
                            if (cord >= 0 && cord < 9)
                                sendbuf[1] = (cord + 49);
                            else
                                status = 1;
                        } while (status == 1);

                        //send cord guess
                        send(ClientSocket, sendbuf, BUFLEN, 0);

                        cout << endl << "guessing " << sendbuf[0] << sendbuf[1] << endl;

                        //recv hit or miss
                        status = recv(ClientSocket, recvbuf, BUFLEN, 0);

                        //Display hit/miss
                        for (int x = 0; x < status; x++)
                        {
                            cout << recvbuf[x];
                        }

                        cout << endl;

                        //If all the boxes have been hit
                        if (HitCounter == 17)
                        {
                            //send game complete
                            strcpy(sendbuf, "game complete!");
                            cout << sendbuf << endl;
                            send(ClientSocket, sendbuf, BUFLEN, 0);
                        }   
                    }
                    cout << "client disconnected" << endl;
                }

                _getch();
                return 0;
            }

Coding:Client

            //Battleship Client
            #include <iostream>     //For basic I/O operations
            #include <conio.h>      //For _getch(); to pause the program
            #include <winsock2.h>   //For network operations
            #include <windows.h>    //Needed by winsock
            #include <ws2tcpip.h>   //Used for and addrinfo related functions
            #include <string>       //For string functions
            #include <time.h>       //For rand() functions  
            #define BUFLEN 64       //Default buffer length
            #define PORT "3490"     //Port to be used

            using namespace std;

            //Global ship names and corresponding letters
            string Shipnames[5] = {
                "Aircraft Carrier",
                "BattleShip",
                "Destroyer",
                "Submarine",
                "patrol Boat",
            };

            char Letter[5] = { 'A', 'B', 'D', 'S', 'P' };

            struct Ship
            {
                //To keep track of hits
                char Hitbox[5];

                //the length of the ship
                int len;

                //X & Y positions
                int X;
                int Y;

                //Direction
                //true = vertical (Y)
                //false = horizontal (X)
                bool Direction;
            };

            bool SendLine(int sockfd, string desc)
            {
                char *Text = new char[BUFLEN];

                cout << desc << endl;
                cin.getline(Text, BUFLEN, '\n');

                if (strcmp(Text, "V") == 0 || strcmp(Text, "v") == 0)
                {
                    delete[] Text;
                    return true;
                }

                if (send(sockfd, Text, BUFLEN, 0) == SOCKET_ERROR)
                    cout << "server down" << endl;

                delete[] Text;
                return false;
            }

            //Translates letter cords to numbers
            //eg: A5 = 15, B7 = 27, E3 = 53
            int TransLettoNumb(char *Cord)
            {
                char Letters[8] = {
                    'A',
                    'B',
                    'C',
                    'D',
                    'E',
                    'F',
                    'G',
                    'H',
                };

                char Lowercase[8] = {
                    'a',
                    'b',
                    'c',
                    'd',
                    'e',
                    'f',
                    'g',
                    'h',
                };

                //Check through upper case
                for (int x = 0; x < 8; x++)
                {
                    if (Cord[0] == Letters[x])
                        return x+1;
                }

                //check through lower case
                for (int x = 0; x < 8; x++)
                {
                    if (Cord[0] == Lowercase[x])
                        return x+1;
                }

                return 0;
            }

            void UpdateShipGrid(char Grid[8][8], Ship ships[])
            {


            }

            //For checking if the server hit a boat
            bool Checkhit(Ship ships[], char Cord[], char ShipGrid[8][8])
            {
                //Translate cords to ints
                int Xcord = TransLettoNumb(Cord);
                int Ycord = (Cord[1] - 48); //we -48 to convert from ascii value

                //Length of ship
                int Len;

                //For each ship
                for (int n = 0; n < 4; n++)
                {
                    //Set length
                    if (n == 0)
                        Len = 5;
                    else if (n == 1)
                        Len = 4;
                    else if (n == 2)
                        Len = 3;
                    else if (n == 3)
                        Len = 3;
                    else if (n == 4)
                        Len = 2;

                    //loop through the hitbox
                    for (int i = 0; i < Len; i++)
                    {
                        //If the x cord equals the ships cords plus hitbox (i), test y cords
                        if (Xcord == (ships[n].X + i))
                        {
                            //loop through the hitbox
                            for (int i = 0; i < Len; i++)
                            {
                                //If the y cord equals the ships cords plus hitbox (i)
                                if (Ycord == (ships[n].X + i))
                                {
                                    //the ship was hit, update the hitbox and grid
                                    ships[n].Hitbox[i] = 'X';
                                    UpdateShipGrid(ShipGrid, ships);
                                    return true;
                                }
                            }
                        }
                    }
                }

                //The ship was not hit
                return false;
            }

            bool sendl(int sockfd, bool hit)
            {
                char *Line = new char[BUFLEN];

                if (hit)
                {
                    Line = "Hit!";
                    cout << "Hit!" << endl;
                }
                else
                {
                    Line = "Miss!";
                    cout << "Miss!" << endl;
                }

                bool var = true;

                if (send(sockfd, Line, strlen(Line), 0) == SOCKET_ERROR)
                    var = false;

                return var;
            }

            void DisplayGrid(char GridA[8][8], char GridB[8][8]) 
            {
                cout << "     Hit Grid          Ship Grid   " << endl;
                cout << "  A B C D E F G H   A B C D E F G H" << endl;
                for (int n = 1; n < 9; n++)
                {
                    cout << n << " ";

                    for (int i = 0; i < 8; i++)
                    {
                        cout << GridA[n][i] << " ";
                    }

                    cout << "| ";

                    for (int t = 0; t < 8; t++)
                    {
                        cout << GridB[n][t] << " ";
                    }
                    cout << endl;
                }
            }

            void InitGrid(char grid[8][8], Ship ships[])
            {
                //For the first dimension (x)
                for (int n = 0; n < 9; n++)
                {
                    //For the second dimension (y)
                    for (int i = 0; i < 9; i++)
                    {
                        //Give the box an empty space
                        grid[i][n] = ' ';
                    }

                }
            }

            void PlaceShips(Ship ships[], char Grid[8][8])
            {
                int randnumb;

                //For each ship
                for (int n = 0; n < 5; n++)
                {
                    //Randomize direction
                    randnumb = rand() % 2;

                    if (randnumb == 1)
                        ships[n].Direction = true;
                    else
                        ships[n].Direction = false;

                    do
                    {
                        randnumb = 0;

                        //randomize x
                        ships[n].X = rand() % 8 + 1;

                        //randomize y
                        ships[n].Y = rand() % 8 + 1;

                        //If direction is true, check y 
                        if (ships[n].Direction)
                        {
                            //If the ship hit the wall
                            if ((ships[n].Y + ships[n].len) > 8)
                                randnumb = 1;
                            else
                            {
                                //Place each hitbox on grid
                                for (int i = 0; i < ships[n].len; i++)
                                    Grid[ships[n].X][(ships[n].Y + i)] = ships[n].Hitbox[i];
                            }
                        }
                        else //else check x
                        {
                            //If the ship hit the wall
                            if ((ships[n].X + ships[n].len) > 8)
                                randnumb = 1;
                            else
                            {
                                //Place each hitbox on grid
                                for (int i = 0; i < ships[n].len; i++)
                                    Grid[(ships[n].X + i)][ships[n].Y] = ships[n].Hitbox[i];
                            }

                        }           

                    } while (randnumb > 0);
                }
            }

            int main(int argc, char **argv)
            {
                // Validate the parameters
                if (argc != 2) 
                {
                    cout << "Syntax: <server-ip>" << endl;
                    _getch();
                    return 1;
                }

                //Quit flag
                bool quit = false;

                //Keep track of hits
                int HitCounter = 0;

                //Initialize random seed
                srand(time(NULL));

                //Declare ships
                Ship ships[5];

                //Initialize ship lengths
                ships[0].len = 5;
                ships[1].len = 4;
                ships[2].len = 3;
                ships[3].len = 3;
                ships[4].len = 2;

                //Declare some winsock variables
                int status;                                 //To keep track of errors
                WSADATA wsaData;                            //For winsock initialization
                SOCKET ServerSocket = INVALID_SOCKET;       //Socket for communicating with server
                struct addrinfo *result = NULL;             //struct to hold address information
                struct addrinfo *Pointer = NULL;            //struct to hold point to next ip
                struct addrinfo address;                    //struct to hold connection information
                char recvbuf1[BUFLEN];                      //Buffer for receiving information
                char recvbuf2[BUFLEN];                      //Extra Buffer for receiving information
                char sendbuf[BUFLEN];                       //Buffer for sending information

                // Initialize Winsock
                status = WSAStartup(MAKEWORD(2, 2), &wsaData);
                if (status != 0)
                {
                    cout << "failed to initialize winsock" << endl;
                    _getch();
                    return 1;
                }

                ZeroMemory(&address, sizeof(address));
                address.ai_family = AF_INET;
                address.ai_socktype = SOCK_STREAM;
                address.ai_protocol = IPPROTO_TCP;
                address.ai_flags = AI_PASSIVE;

                //Get IP and port info
                status = getaddrinfo(argv[1], PORT, &address, &result);
                if (status != 0)
                {
                    cout << "getaddrinfo failed with error: " << WSAGetLastError() << endl;
                    freeaddrinfo(result);
                    _getch();
                    return 1;
                }

                // Attempt to connect to an address until one succeeds
                for (Pointer = result; Pointer != NULL; Pointer = Pointer->ai_next) {

                    // Create a SOCKET for connecting to server
                    ServerSocket = socket(Pointer->ai_family, Pointer->ai_socktype, Pointer->ai_protocol);
                    if (ServerSocket == INVALID_SOCKET) 
                    {
                        printf("socket failed with error: %ld\n", WSAGetLastError());
                        WSACleanup();
                        _getch();
                        return 1;
                    }

                    // Connect to server.
                    status = connect(ServerSocket, Pointer->ai_addr, (int)Pointer->ai_addrlen);
                    if (status == SOCKET_ERROR) 
                    {
                        closesocket(ServerSocket);
                        ServerSocket = INVALID_SOCKET;
                        continue;
                    }
                    break;
                }



                if (ServerSocket == INVALID_SOCKET)
                {
                    cout << "could not connect " << endl;
                    _getch();
                    return 1;
                }
                else
                    cout << "connected to " << argv[1] << ":" << PORT << endl;

                //Done with the results
                freeaddrinfo(result);

                //set up game...

                //Grids that will be displayed
                char HitGrid[8][8];
                char ShipGrid[8][8];

                //Initialize grids
                InitGrid(HitGrid, ships);
                InitGrid(ShipGrid, ships);

                //Initialize ship hitboxes
                for (int x = 0; x <5; x++)
                {
                    //Initialize hitbox
                    for (int i = 0; i<5; i++)
                        ships[x].Hitbox[i] = Letter[x];
                }

                //Randomize ship locations
                PlaceShips(ships, ShipGrid);

                status = 1;

                while (status > 0)
                {
                    //Ask for cords 
                    cout << "Enter a coord to bomb or press v to view grid" << endl;
                    cin.getline(sendbuf, BUFLEN, '\n');


                    //If user type 'v' then display grids
                    while (strcmp(sendbuf, "V") == 0 || strcmp(sendbuf, "v") == 0)
                    {
                        //Display the grids
                        DisplayGrid(HitGrid, ShipGrid);

                        //Ask for cords 
                        cout << endl << "Enter a coord to bomb or press v to view grid" << endl;
                        cin.getline(sendbuf, BUFLEN, '\n');
                    }

                    //send cords
                    send(ServerSocket, sendbuf, BUFLEN, 0); 

                    //recv hit/miss
                    status = recv(ServerSocket, recvbuf1, BUFLEN, 0);

                    //If we hit a ship, mark it on the hit grid
                    if (recvbuf1[0] == 'H')
                    {
                        //Recieve ship that was hit
                        status = recv(ServerSocket, recvbuf2, BUFLEN, 0);

                        //Display shipname
                        for (int x = 0; x < status; x++)
                        {
                            cout << recvbuf2[x];
                        }

                        cout << " was hit!" << endl;

                        //Update the hit grid
                        HitGrid[(sendbuf[1] - 48)][(TransLettoNumb(sendbuf) -1)] = recvbuf2[0];
                    }
                    else
                    {
                        HitGrid[(sendbuf[1] - 48)][(TransLettoNumb(sendbuf) - 1)] = 'X';

                        //Display hit/miss
                        for (int x = 0; x < status; x++)
                        {
                            cout << recvbuf1[x];
                        }

                        cout << endl;
                    }

                    //recv cord
                    status = recv(ServerSocket, recvbuf1, BUFLEN, 0);

                    cout << endl << "server bombed cord " << recvbuf1[0] << recvbuf1[1] << endl;

                    //Check if it was a hit or miss and reply to server
                    if (!Checkhit(ships, recvbuf1, ShipGrid))
                        sendl(ServerSocket, false);
                    else
                    {
                        sendl(ServerSocket, true);

                        //Add to hit counter
                        HitCounter++;
                    }

                    //update the ship grid
                    ShipGrid[(recvbuf1[1] - 48)][(TransLettoNumb(recvbuf1) - 1)] = 'X';

                    //Clear buffer
                    memset(recvbuf1, 0, sizeof(recvbuf1));
                    memset(recvbuf2, 0, sizeof(recvbuf2));

                    if (HitCounter > 17)
                    {
                        cout << endl << "the server one the game!" << endl;
                        _getch();
                        return 0;
                    }
                }

                _getch();
                return 0;
            }
mathias loy
  • 15
  • 1
  • 9
  • Try compiling them in Ubuntu. Replace all functions that aren't supported with the equivalent available in Ubuntu. – Captain Obvlious May 29 '15 at 01:50
  • When i try to compile the program, there are error like conio.h not found, then after i removed it, it said winsock2.h and window.h error. Please assist to advice. Thanks alot – mathias loy May 29 '15 at 02:12
  • This is a rather broad question with no simple answer. I don't know how many people are going to be willing to sift through the entire code of your project to point out all the windows specific bits. Frankly, you would be better off starting with a fresh program in ubuntu and moving over & replacing a single function at a time. – Aumnayan May 29 '15 at 02:19
  • possible duplicate of [Cross-platform sockets](http://stackoverflow.com/questions/28027937/cross-platform-sockets) – Captain Obvlious May 29 '15 at 02:41

1 Answers1

-1

from my experience it should not be a big problem to port a socket program to ubuntu or vice versa.

The first advice I can give you is to separate the (OS specific) socket code from your game code. My Suggestion is to create seperate classes for this.

Next, the headers conio.h, winsock2.h, windows.h and ws2tcpip.h don't exist in ubuntu (and Linux in general) but the functions exist in different headers. Have a look at the following tutorial which I like very much. It explains a complete tutorial: http://www.linuxhowtos.org/C_C++/socket.htm

Hope this helps

Thomas Sparber
  • 2,827
  • 2
  • 18
  • 34