2013-04-07 97 views
0

我想在C++中编写一个irc bot,并且已经考虑到连接和设置我的昵称以及身份,ping也在运行。我遇到的唯一问题是加入一个频道。服务器继续发送回“JOIN:未知的命令”我相信下面的线是最相关的:为什么irc发送“命令未知”?

#define JOIN "JOIN #test\r\n" 
send(IrcSocket, JOIN, strlen(JOIN),0); 

上关的机会,没有任何东西可以从我包括这可能是有点的entrie程序来解决一个眼睛。

#define WIN32_LEAN_AND_MEAN 
#include <iostream> 
#include <windows.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdio.h> 
#include <string> 
#pragma comment(lib, "Ws2_32.lib") 

int main() 
{ 
    WSADATA wsaData; 
    int iresult=WSAStartup(MAKEWORD(2,2),&wsaData); 
    if(iresult!=0) 
    { 
        printf("WSAStartup Failed: %d \n", iresult); 
        return 1; 
    } 
    struct addrinfo *result=NULL, *ptr=NULL, hints; 
    ZeroMemory(&hints,sizeof(hints)); 
    hints.ai_family=AF_INET; 
    hints.ai_socktype=SOCK_STREAM; 
    hints.ai_protocol=IPPROTO_TCP; 
    #define DEFAULT_PORT "6667" 
    #define DEFAULT_IP "192.168.0.10" 
    iresult = getaddrinfo(DEFAULT_IP,DEFAULT_PORT,&hints,&result); 
    if(iresult!=0) 
    { 
        printf("getaddrinfo failed: %d\n", iresult); 
        WSACleanup(); 
        return 1; 
    } 
    SOCKET IrcSocket= INVALID_SOCKET; 
    ptr=result; 
    IrcSocket=socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol); 
    if (IrcSocket == INVALID_SOCKET) 
    { 
     printf("Error at socket(): %d \n", WSAGetLastError()); 
     freeaddrinfo(result); 
     WSACleanup(); 
     return 1; 
    } 
    iresult=connect(IrcSocket,ptr->ai_addr,ptr->ai_addrlen); 
    if(iresult==SOCKET_ERROR) 
    { 
     closesocket(IrcSocket); 
     IrcSocket=INVALID_SOCKET; 
     freeaddrinfo(result); 
    } 


    if(IrcSocket == INVALID_SOCKET) 
    { 
     printf("Unable to connect to irc server!"); 
     WSACleanup(); 
     return 1; 
    } 
    std::cout<<("connection made\n"); 
    #define NICK "NICK bottester\r\n" 
    #define IDENT "USER bottester 0 0 bottester\r\n" 
    #define JOIN "JOIN #test\r\n" 
    char stringbuffer[256]; 

    iresult=send(IrcSocket,NICK, strlen(NICK),0); 
    if(iresult == SOCKET_ERROR) 
    { 
     printf("send failed: %d\n", WSAGetLastError()); 
     closesocket(IrcSocket); 
     WSACleanup(); 
     std::cin.get(); 
     return 1; 
    } 
    iresult=send(IrcSocket, IDENT, strlen(IDENT),0); 
    if(iresult == SOCKET_ERROR) 
    { 
     printf("send failed: %d\n", WSAGetLastError()); 
     closesocket(IrcSocket); 
     WSACleanup(); 
     std::cin.get(); 
     return 1; 
    } 
    std::cout<<"entering ping loop\n"; 
    char pingnumber[128]; 
    char pinganswer[17]="PONG :"; 
    #define PRMSG "PRIVMSG test :TESTBOT IS HERE!\r\n" 
    for(;;) 
    { 
      memset(stringbuffer,0,256); 
      recv(IrcSocket,stringbuffer,sizeof(stringbuffer),0); 
      for(int j=0;j<strlen(stringbuffer);j++) 
      { 
        std::cout<<j<<stringbuffer[j]<<"\n"; 
      if(stringbuffer[j]=='P' && stringbuffer[j+1]=='I' && stringbuffer[j+2]=='N' && stringbuffer[j+3]=='G') 
      { 
      memset(pingnumber,0,10); 
      std::memcpy(pingnumber, stringbuffer+j+6,10); 
      std::memcpy(pinganswer+6,pingnumber,10); 
      std::memcpy(pinganswer+16, "\r\n",strlen("\r\n")); 
      send(IrcSocket,pinganswer,strlen(pinganswer),0); 
      std::cout<< "PINGED<"<<pingnumber<<"\n"; 
      iresult=send(IrcSocket, JOIN, strlen(JOIN),0); 
      std::cout<< "JOINED\n"; 
      send(IrcSocket, PRMSG, strlen(PRMSG),0); 
      } 
      } 
    } 


} 
+0

连接命令不是以'/'开始的吗? – Petesh 2013-04-07 22:20:28

+0

当你使用客户端是的,当它只是协议,我不相信如此。 – 2013-04-07 23:42:18

+1

在加入之前,您不会处理任何回复 - 之前的某些内容可能会失败,例如USER或NICK请求。 – Petesh 2013-04-08 10:15:53

回答

0

您在发送JOIN之前并未等待注册完成。

你的客户太简单了,真的。为了获得您想要的效果,您可以在USER/NICK命令和JOIN命令之间进行睡眠。

虽然正确的非kludgy解决方案是使用轮询,选择等方式来进行正确的发送/接收轮询循环,但要等待001数字(在连接注册后收到的第一个正确的数字)或更正确地使用RPL_ENDOFMOTD (376)或ERR_NOMOTD(422)。收到这一行后,发送你的JOIN。

参见:https://tools.ietf.org/html/rfc1459

另见:https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

此外,还有更多你真的需要应对,而不是PING做一个正常运作的客户,但是这是另一天。有些服务器在注册期间发送'安全'PING,您必须在服务器接受连接并发送001数字之前做出响应。如果您没有对此做出响应,您的连接永远不会注册,并最终ping超时。