2013-04-07 102 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超時。