0

I'm creating a game in C++ for a university project which requires some feature of networking using Sockets. My module lecturer gave us example code of working (local machine) client/servers to show us how it works. He has the following code for setting up the socket, which works fine:

#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

#define SERVERIP     "127.0.0.1"
#define SERVERPORT   5555

void main(){
    WSADATA w;
    int error = WSAStartup(0x0202, &w);
    if (error != 0)
    {
        die("WSAStartup failed");
    }
    if (w.wVersion != 0x0202)
    {
        die("Wrong WinSock version");
    }

    // Create a TCP socket that we'll use to listen for connections.
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == INVALID_SOCKET)
    {
        die("socket failed");
    }

    // Fill out a sockaddr_in structure to describe the address we'll listen on.
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(SERVERIP);
    // htons converts the port number to network byte order (big-endian).
    serverAddr.sin_port = htons(SERVERPORT);

    // Bind the server socket to that address.
    if (bind(serverSocket, (const sockaddr *) &serverAddr, sizeof(serverAddr)) != 0)
    {
        die("bind failed");
    }
}

However, when I replicate most of the code, bind(...) function keeps returning -1, as opposed to the 0 in my lecturers example. Here is the relevant part of my code, using classes:

TCPSocket.h

#define SERVERIP     "127.0.0.1"
#define SERVERPORT   5555

#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

class TCPSocket {
public:
    TCPSocket();
    ~TCPSocket();

    void SetupServer(char* serverIP_, int serverPort_, int messageSize_);

protected:

private:

    SOCKET m_socket;
    sockaddr_in m_serverAddress;

    char* m_serverIP;
    int m_serverPort;
    int m_messageSize;
};

TCPSocket.cpp

TCPSocket::TCPSocket() {
    // Initialise WinSock Library, version 2.2
    WSADATA w;
    int error = WSAStartup(0x0202, &w);
    if(error != 0) {
        //error
        int i = 0;
    }
    if(w.wVersion != 0x0202) {
        //error
        int i = 0;
    }
}

void TCPSocket::SetupServer(char* serverIP_, int serverPort_, int messageSize_) {
    m_serverIP = serverIP_;
    m_serverPort = serverPort_;
    m_messageSize = messageSize_;

    // Create TCP socket
    m_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(m_socket == INVALID_SOCKET) {
        //error
        int i = 0;
    }

    m_serverAddress.sin_family = AF_INET;
    m_serverAddress.sin_addr.s_addr = inet_addr(SERVERIP);
    m_serverAddress.sin_port = htons(SERVERPORT);       // htons: port -> network byte order (big-endian)

    // Bind server socket to address
    int bindex = bind(m_socket, (const sockaddr *) &m_serverAddress, sizeof(m_serverAddress));
    if(bindex != 0) {
        //error
        int a = 0;
    }

}
DeanoMachino
  • 59
  • 2
  • 12
  • 3
    Try calling [`WSAGetLastError`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741580%28v=vs.85%29.aspx) and see which [error code](https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx) is returned. – Paul Rooney Nov 24 '15 at 23:46
  • I don't believe it's the reason for the error, but if you're passing `serverIP_` and `serverPort_` to the `SetupServer` function, why are you still using the defined macros for `SERVERIP` and `SERVERPORT` in the calls to `inet_addr()` and `htons` ? – Alnitak Nov 24 '15 at 23:48
  • 1
    Just realised I made a silly mistake: I was running the `SetupServer()` function in an update loop and the error was being caught on the second iteration. – DeanoMachino Nov 24 '15 at 23:51
  • @Alnitak I originally used the passed in variables, but since `m_serverIP` wasn't a `const` I felt that might've been causing an error (evidently not though). – DeanoMachino Nov 24 '15 at 23:53
  • 2
    Also, a general advice: `WSAStartup` should only be called once in the program (typically somewhere at the beginning of `main`; don't forget to also call its pair `WSACleanup` at the end). Placing it in the ctor, would result it being called every time you instantiate your class (although probably not the case here if you only have one instance). – CristiFati Nov 24 '15 at 23:56
  • @CristiFati Yeah, while the program is written to include the code for both the server and client, only one socket should be open for each instance of the program. – DeanoMachino Nov 25 '15 at 00:14
  • Extending on @CristiFati 's point, this is SPARTA!!!! Err... C++. Make a dummy class with `WSAStartup` in the constructor and `WSACleanup` in the destructor. Then create one global instance of the dummy. Scoping handles everything for you. – user4581301 Nov 25 '15 at 00:17
  • You better use `getaddrinfo` to init address. you can look here for a sample: http://stackoverflow.com/questions/19431370/how-to-use-getaddrinfo-to-choose-default-free-port-for-all-interfaces – SHR Nov 25 '15 at 00:25

1 Answers1

0

As I said in a comment, I made a silly mistake outwith the scope of the included code: basically I was running the SetupServer() function within an update loop and the error was being caught on the second iteration of the update. Besides that, the code is perfectly functional.

DeanoMachino
  • 59
  • 2
  • 12