简体   繁体   English

使用套接字连接到TeamSpeak服务器查询(C ++)

[英]Connecting to TeamSpeak server query with sockets (C++)

At the moment I'm trying to write a program (C++) to connect to my TS3 server and run a query. 目前,我正在尝试编写一个程序(C ++)以连接到我的TS3服务器并运行查询。
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/ ). 当我使用SocketTest程序( http://sourceforge.net/projects/sockettest/ )测试套接字时,套接字本身运行良好。 Nevertheless I'm not able to connect to my TS3 server and run a query. 但是,我无法连接到我的TS3服务器并运行查询。
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. 如果我使用SocketTest程序测试了我的代码(包括上面的函数),则一切正常,客户端正在连接,服务器接收到消息,但不适用于TS3服务器。 The logs of the TS3 server show no sign of a connecting client. TS3服务器的日志未显示连接客户端的迹象。
Is there any issue with my code or is there another reason why this is not working with my TS3 server? 我的代码有任何问题吗?或者还有其他原因导致我的TS3服务器不工作吗?

PS: I added localhost (127.0.0.1) to the server query whitelist of my TS3 server. PS:我在我的TS3服务器的服务器查询白名单中添加了本地主机(127.0.0.1)。
PSS: I tested several TS3 servers, still the same. PSS:我测试了几台TS3服务器,但仍然相同。


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. 实际上,无论何时连接到TS3服务器查询或发送命令,TS3服务器查询都会发送数据(欢迎消息,错误等)。 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.) (执行recv()命令时,使用sizeof(buffer)而不是strlen(buffer) (或类似的东西)也很重要,否则接收发送的数据将无效。)

As far as your call to connect() is concerned, your code is fine, except for a lack of error handling. 就您对connect()调用而言,您的代码很好,但缺少错误处理。

But why are you using the MSG_OOB flag on send() ? 但是,为什么要在send()上使用MSG_OOB标志? 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() . 另外,在将字符串文字传递给send() sizeof()时,使用sizeof()是错误的,请改用strlen() ,或者更好的方法是将数据放入std::string并传递其c_str()的返回值,用于send() length()方法。

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. 另外,您不会读取TS3服务器发送给客户端的任何响应,因此您不知道命令是否真正成功,甚至不知道是否与TS3服务器进行通信。

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: 您可以通过执行以下论坛文章中的内容来验证TS3服务器:

How to use the Server Query 如何使用服务器查询

Use a command-line telnet app for testing. 使用命令行telnet应用进行测试。 If that does not work, your app is not going to work, either. 如果这不起作用,那么您的应用也将无法工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM