用套接字连接到TeamSpeak服务器查询(c++)
Connecting to TeamSpeak server query with sockets (C++)
目前我正试图写一个程序(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 1n", sizeof("use 1n"), 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服务器不能工作?
注::我在TS3服务器的服务器查询白名单中添加了localhost(127.0.0.1)。
附注:我测试了几个TS3服务器,还是一样的。
解决方案(编辑):
解决办法似乎很简单。实际上,只要您连接到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 1n", strlen("use 1n"), 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();
(我知道在上面的代码中没有错误检查,但是我故意省略了它。如果在实际环境中运行此代码,显然需要进行一些错误检查。
除此之外,我还检查了环境中的错误,然后用这段代码说明我的问题。
(在执行recv()
命令时,使用sizeof(buffer)
而不是strlen(buffer)
(或类似的东西)也很重要,否则接收发送的数据将无法工作)
就您对connect()
的调用而言,除了缺乏错误处理之外,您的代码很好。
但是为什么在send()
上使用MSG_OOB
标志呢?你不应该用这个。此外,当将字符串文字传递给send()
时使用sizeof()
是错误的,请使用strlen()
代替,或者更好的做法是将数据放入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 1n") == SOCKET ERROR)
{
ret = WSAGetLastError();
// process error as needed ...
goto donesock;
}
// TODO: read the response...
if (sendCommand(sock, "login username passwordn") == 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, "logoutn") == SOCKET_ERROR)
{
ret = WSAGetLastError();
// process error as needed ...
goto donesock;
}
// TODO: read the response...
if (sendCommand(sock, "quitn") == SOCKET_ERROR)
{
ret = WSAGetLastError();
// process error as needed ...
goto donesock;
}
donesock:
closesocket(sock);
cleanup:
WSACleanup();
finished:
您可以通过执行以下论坛文章所述的操作来验证TS3服务器:
如何使用Server Query
使用命令行telnet应用程序进行测试。
- Mongodb c++驱动程序:如何查询元素的数组
- 查询SQLite数据库中的日期
- 如何在ArangoDb AQL查询中指定数据库
- Qt SQLite没有查询或参数计数不匹配
- 如何使用c++在VS 2019上运行SQL查询
- 从返回的顶点缓冲区查询顶点结构
- 以非特权用户身份查询 NTFS 特殊文件的元数据?
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- 查询 NFS 上的提升进程间::file_lock
- Qt JSON – 从子项查询
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 无法从 Win10 中的 IDirectDraw7 查询 IDirect3D7
- 如何查询以确定我的 MacOS/X 应用程序是否处于应用程序午睡模式?
- 在子数组中查找多个查询的不同(唯一)值的数量
- DNS 查询格式标头结构中的小字节序问题
- QSql查询行受影响的结果
- C++库相关查询
- 优化使用 C++ 查询 SQLite DB 中超过 5000 万条数据记录的方式
- MongoDB 使用数组中的 OR 条件构建查询
- IAR C 编译器开关:快速查询