您好我正在处理一个向telnet服务器发送命令的程序。
这是我的代码:
int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo* result;
int res = getaddrinfo("192.168.56.101", "23", &hints, &result);
if (res)
{
std::cout << "failed to getaddrinfo" << std::endl;
}
SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (connect(sock, result->ai_addr, (int)result->ai_addrlen) != SOCKET_ERROR && sock != INVALID_SOCKET)
{
std::cout << "connected";
char* buf = "md c:\\testfolder\r\n";
std::cout << send(sock, buf, sizeof("md c:\\testfolder\r\n"), 0);
const int size = 255;
char out[size];
memset(out, 0, size);
while (true)
{
res = recv(sock, out, size, 0);
std::cout << res << std::endl; // this outputs 21
}
}
else
{
std::cout << res;
}
std::cin.get();
return 0;
}
发送命令后,telnet服务器应在名为C:\\ directory
的{{1}}中创建一个文件夹,但它没有这样做。 testfolder
向我发送垃圾值。
我已阅读RFC 854,但它真的很难阅读。所以,请向我解释我的代码出错了。
答案 0 :(得分:0)
您的代码存在一些问题。最重要的是,如果getaddrinfo()
失败,您将继续执行其余代码,因为result
无效,因此会崩溃。而且,您忽略了send()
和recv()
的返回值。而你实际上并没有输出你收到的数据。
尝试更像这样的事情:
int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsaData;
int res = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (res != 0)
{
std::cerr << "failed to init Winsock, error " << res << std::endl;
return 1;
}
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo* result;
res = getaddrinfo("192.168.56.101", "23", &hints, &result);
if (res != 0)
{
std::cerr << "failed to getaddrinfo, error " << res << std::endl;
WSACleanup();
return 1;
}
SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (sock == INVALID_SOCKET)
{
res = WSAGetLastError();
std::cerr << "failed to create socket, error " << res << std::endl;
freeaddrinfo(result);
WSACleanup();
return 1;
}
if (connect(sock, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
res = WSAGetLastError();
std::cerr << "failed to connect, error " << res << std::endl;
freeaddrinfo(result);
closesocket(sock);
WSACleanup();
return 1;
}
freeaddrinfo(result);
std::cout << "connected";
std::string cmd = "md c:\\testfolder\r\n";
const char *buf = cmd.c_str();
int size = cmd.length();
do
{
res = send(sock, buf, size, 0);
if (res == SOCKET_ERROR)
{
res = WSAGetLastError();
std::cerr << "failed to send, error " << res << std::endl;
closesocket(sock);
WSACleanup();
return 1;
}
buf += res;
size -= res;
}
while (size > 0);
char out[255];
while (true)
{
res = recv(sock, out, sizeof(out), 0);
if (res == SOCKET_ERROR)
{
res = WSAGetLastError();
std::cerr << "failed to recv, error " << res << std::endl;
closesocket(sock);
WSACleanup();
return 1;
}
if (res == 0)
{
std::cout << "disconnected" << std::endl;
break;
}
std::cout.write(out, res);
}
closesocket(sock);
WSACleanup();
return 0;
}
现在,如果您要连接到实际 Telnet服务器,而不仅仅是在标准Telnet端口上运行的任意TCP服务器,那么您需要实现实际 Telnet协议。这意味着处理和响应Telnet命令(WILL
,WONT
等),协商Telnet选项(消息缓冲区大小,字符集支持等),等等。 RFC 854中描述的所有内容以及其他相关RFC。它可能很难阅读(不是真的),但你需要阅读和理解它。您从服务器收到的“垃圾”可能根本不是垃圾。这是您尚未解释的Telnet命令。
简而言之,Telnet命令被转义,因此您必须逐字节处理接收到的数据,如果遇到转义字节0xFF
,则下一个字节是命令类型,并且取决于该命令是什么,可能还有更多字节来完成命令。其他不是命令的东西只是原始数据。