0

目前我正在尝试编写一个程序(C++)来连接到我的 TS3 服务器并运行查询。
为了完成这个任务,我使用了一个套接字。当我使用 SocketTest 程序 ( http://sourceforge.net/projects/sockettest/ )对其进行测试时,套接字本身工作正常。不过,我无法连接到我的 TS3 服务器并运行查询。
我正在使用的代码(更具体地说是函数):

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();

如果我使用 SocketTest 程序测试我的代码(包括上面的函数),一切正常,客户端正在连接并且服务器接收消息,但它不适用于我的 TS3 服务器。TS3 服务器的日志没有显示连接客户端的迹象。
我的代码是否有任何问题,或者是否有其他原因导致这不适用于我的 TS3 服务器?

PS:我将localhost(127.0.0.1)添加到我的TS3服务器的服务器查询白名单中。
PSS:我测试了几台TS3服务器,还是一样。


解决方案(编辑):
解决方案似乎很简单。事实上,只要您连接到它或发送命令,TS3 服务器查询就会发送数据(欢迎消息、错误等)。为了让它工作,我只需要接收发送的数据,这就是一切。
代码如下:

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();

(我知道上面的代码没有错误检查,但我特意省略了。如果你在真实环境中运行这段代码,你显然需要一些错误检查。
除此之外,我还检查了我的环境中的错误在用这段代码说明我的问题之前。)

sizeof(buffer)(在执行命令时使用代替strlen(buffer)(或类似的东西)也很重要recv(),否则接收发送的数据将不起作用。)

4

1 回答 1

0

就您的调用connect()而言,您的代码很好,除了缺少错误处理。

但是你为什么要在上面使用MSG_OOB标志send()呢?你不应该使用它。此外,您sizeof()在将字符串文字传递给时的使用send()是错误的,strlen()而是使用,或者更好的方法是将数据放入 a并将其和方法std::string的返回值传递给.c_str()length()send()

此外,您没有读取 TS3 服务器发送给您的客户端的任何响应,因此您不知道您的命令是否真的成功,或者即使您开始与 TS3 服务器通信。

尝试更多类似的东西:

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:

您可以通过执行以下论坛文章中的说明来验证您的 TS3 服务器:

如何使用服务器查询

使用命令行 telnet 应用程序进行测试。如果这不起作用,您的应用程序也将无法运行。

于 2015-05-25T23:16:41.963 回答