Connecting to TeamSpeak server query with sockets (C++)

1.8k Views Asked by At

At the moment I'm trying to write a program (C++) to connect to my TS3 server and run a query.
To accomplish this task, I'm using a socket. The socket itself is working fine as I tested it with the SocketTest program (http://sourceforge.net/projects/sockettest/). Nevertheless I'm not able to connect to my TS3 server and run a query.
The code I'm using (more specifically the function):

struct sockaddr_in addr;
WSAStartup(MAKEWORD(1, 1), &wD);
std::memset(&addr, 0, sizeof(struct sockaddr_in));
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
addr.sin_family = AF_INET;
addr.sin_port = htons(10011);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr*)&addr, sizeof(addr));
send(sock, "use 1\n", sizeof("use 1\n"), MSG_OOB);
send(sock, "login ****** ********\n", sizeof("login ****** ********\n"), MSG_OOB);
send(sock, "clientpoke clid=2 msg=Hallo!\n", sizeof("clientpoke clid=2 msg=Hallo!\n"), MSG_OOB);
closesocket(sock);
WSACleanup();

If I test my code (including the function above) with the SocketTest program, everything is working, the client is connecting and the server receives the messages, but it's not working with my TS3 server. The logs of the TS3 server show no sign of a connecting client.
Is there any issue with my code or is there another reason why this is not working with my TS3 server?

P.S.: I added localhost (127.0.0.1) to the server query whitelist of my TS3 server.
P.S.S.: I tested several TS3 servers, still the same.


SOLUTION (Edit):
The solution seems to be very easy. In fact the TS3 server query sends data (welcome messages, errors, etc.) whenever you connect to it or send a command. To get this working, I just needed to receive the sent data, that's everything.
The code would be the following then:

char buffer[1024];
struct sockaddr_in addr;
WSAStartup(MAKEWORD(2, 2), &wD);
std::memset(&addr, 0, sizeof(struct sockaddr_in));
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
addr.sin_family = AF_INET;
addr.sin_port = htons(10011);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr*)&addr, sizeof(addr));
send(sock, "use 1\n", strlen("use 1\n"), NULL);
recv(sock, buffer, sizeof(buffer), NULL);
send(sock, "login Daniel ********\n", strlen("login Daniel ********\n"), NULL);
recv(sock, buffer, sizeof(buffer), NULL);
send(sock, "clientpoke clid=1 msg=Hello!\n", strlen("clientpoke clid=1 msg=Hello!\n"), NULL);
recv(sock, buffer, sizeof(buffer), NULL);
closesocket(sock);
WSACleanup();

(I know that there's no error checking in the code above, but I spared it out purposely. If you're running this code in a real environment, you obviously need some error checking.
Besides that, I also checked the errors in my environment before stating my problem here with this code.)

(It's also important that you use sizeof(buffer) instead of strlen(buffer) (or similar things) when you execute the recv() command, otherwise receiving the sent data won't work.)

1

There are 1 best solutions below

0
On

As far as your call to connect() is concerned, your code is fine, except for a lack of error handling.

But why are you using the MSG_OOB flag on send()? You should not be using that. Also, your use of sizeof() when passing string literals to send() is wrong, use strlen() instead, or better would be to put the data into a std::string and pass the return value of its c_str() and length() methods to send().

Also, you are not reading any of the responses that the TS3 server sends to your client, so you don't know if your commands are actually succeeding, or even if you are communicating with a TS3 server to begin with.

Try something more like this:

int sendCommand(SOCKET sock, const std::string &cmd)
{
    const char* ptr = cmd.c_str();
    int len = cmd.length();

    while (len > 0)
    {
        int numSent = send(sock, ptr, len, 0);
        if (numSent == SOCKET_ERROR)
            return SOCKET_ERROR;

        ptr += numSent;
        len -= numSent;
    }

    return 0;
}

// TODO: read the response...

WSADATA wD = {0};
int ret = WSAStartup(MAKEWORD(1, 1), &wD);
if (ret != 0)
{
    // process error as needed ...
    goto finished;
}

SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto cleanup;
}

struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(10011);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto donesock;
}

// TODO: read the server's initial prompt...

if (sendCommand(sock, "use 1\n") == SOCKET ERROR)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto donesock;
}

// TODO: read the response...

if (sendCommand(sock, "login username password\n") == SOCKET_ERROR)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto donesock;
}

// TODO: read the response...

if (sendCommand(sock, "clientpoke clid=2 msg=Hallo!\n") == SOCKET_ERROR)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto donesock;
}

// TODO: read the response...

// ...

if (sendCommand(sock, "logout\n") == SOCKET_ERROR)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto donesock;
}

// TODO: read the response...

if (sendCommand(sock, "quit\n") == SOCKET_ERROR)
{
    ret = WSAGetLastError();
    // process error as needed ...
    goto donesock;
}

donesock:
closesocket(sock);

cleanup:
WSACleanup();

finished:

You can verify your TS3 server by doing what the following forum article says:

How to use the Server Query

Use a command-line telnet app for testing. If that does not work, your app is not going to work, either.