2016-12-28 84 views
0

我試圖在C中製作一個IRC機器人。當機器人嘗試連接到IRC服務器時,它會進入一個無限循環,它不會收到任何內容。 我不確定這是因爲我加入IRC服務器的進程格式錯誤,或者我缺少一些應該發送/接收的數據。IRC機器人故障

#include<stdio.h> 
#include<sys/socket.h> 
#include<netdb.h> 
#include<string.h> 
#include<stdlib.h> 
#include<time.h> 


#define MAXSIZE 4096 

void delay(int milliseconds) 
{ 
    long pause; 
    clock_t now; 

    pause = milliseconds*(CLOCKS_PER_SEC/1000);//set delay using 
    now = clock(); 
    while(now < pause) 
     now = clock(); 
} 

int send_data(int sockfd, char message[]) 
{ 
    send(sockfd, message, strlen(message), 0); 
    printf("OUT: %s\n", message); 
    return 1; 
} 

int recv_data(int sockfd, char *message) 
{ 
    int n; 
    n = recv(sockfd, message, MAXSIZE, 0); 
    printf("IN: %s\n", message); 
    return n; 
} 

int tcp_connect(int *sockfd, char server[], char port[]) 
{ 
    //declare variables 
    struct addrinfo hints, *res; 

    //zero out structures 
    memset(&hints,0,sizeof(hints)); 
    hints.ai_family = AF_INET; 
    hints.ai_socktype = SOCK_STREAM; 

    //query DNS server for IP address and port 
    getaddrinfo(server,port,&hints,&res); 

    //create socket for data transmission 
    *sockfd = socket(res->ai_family,res->ai_socktype,0); 
    if (*sockfd < 0) 
    { 
     printf("failure to create socket\n"); 
     return 0; 
    } 

    //connect to server side port using created socket 
    if (connect(*sockfd, res->ai_addr, res->ai_addrlen)!= 0) 
    { 
     printf("failure to connect to port\n"); 
     return 0; 
    } 

    freeaddrinfo(res); 
    return 1; 
} 

int irc_auth(int sockfd) 
{ 
    //create and start clock 
    clock_t start_t; 
    start_t = clock(); 

    //seed RNG with clock output 
    srand(start_t); 

    //generate necessary variables 
    char name[15] = "bot"; 
    char user[35] = "USER "; 
    char nick[20] = "NICK "; 
    char join[20] = "JOIN #randChat\r\n"; 
    int i,id; 

    //generate random character for ID tag A-Z 
    for(i=0; i<5; i++) 
    { 
     id = rand() % 91; 
     if(id < 65) 
     { 
      while(id < 65) 
      { 
       id = rand() % 91; 
      } 
     } 
     name[strlen(name)] = id; 
    } 
    //append return and null to string 
    strcat(nick,name); 
    strcat(nick,"\r\n"); 

    //append to finish creating USER IRC command 
    strcat(user,name); 
    strcat(user," 8 * :"); 
    strcat(user,name); 
    strcat(user,"\r\n"); 

    //send data to server 
    send_data(sockfd,user); 
    delay(1000); 
    send_data(sockfd,nick); 
    delay(1000); 
    send_data(sockfd,join); 

    return 1; 
} 
int main (int argc, char *argv) 
{ 
//variables 
    int sockfd, n, flag; 
    char *mesg_in = malloc(sizeof(char) * MAXSIZE); 
    char *pos; 
    char nick[30]; 

    char *mesg_out = malloc(sizeof(char) * MAXSIZE); 

    //connect to port 6667 of irc.freenode.org using tcp 
    while(flag<1) 
    { 
     if(tcp_connect(&sockfd,"irc.freenode.org","6667") == 1) 
     { 
      flag = 1; 
     } 
    } 

    //IRC channel authentication 
    irc_auth(sockfd); 

    //command loop 
    while(1) 
    { 
     mesg_in[0] = 0;// zero out message 
     //memset(mesg_in,0,strlen(mesg_in)); 
     n = recv_data(sockfd,mesg_in);// pull message from channel 

     if (n > 0)// check to see if it recieved a command 
     { 
      mesg_in[n] = 0;// set null at the end of recieved data 

      //respond to ping commands from server 
      if(strstr(mesg_in,"PING") != NULL) 
      { 
       mesg_out[0] = 0;// zero out message 
       pos = strstr(mesg_in," ")+1;// point to data needed 
       //append to out bound message 
       sprintf(mesg_out,"PONG %s\r\n",pos); 
       //send outbound message 
       send_data(sockfd,mesg_out); 
      } 
     } 
    } 
} 

任何和所有幫助將不勝感激

+1

wireshark和調試器是你應該熟悉的工具。 – Olaf

回答

2

不管其他問題有可能是,delay()就是其中之一。你在這個測試程序中的功能,等待兩秒鐘,然後同時打印1 2 3,因爲它只考慮從程序開始時的流逝時間,而不是從當前時刻開始。

#include <stdio.h> 
#include <time.h> 

void delay(int milliseconds) 
{ 
    long pause; 
    clock_t now; 
    pause = milliseconds*(CLOCKS_PER_SEC/1000);//set delay using 
    now = clock(); 
    while(now < pause) 
     now = clock(); 
} 

int main (void) 
{ 
    delay(2000); 
    printf("1\n"); 

    delay(2000); 
    printf("2\n"); 

    delay(2000); 
    printf("3\n"); 

    return 0; 
} 

這個版本打印1 2 3每兩週秒鐘的間隔

#include <stdio.h> 
#include <time.h> 

void delay(clock_t milliseconds) 
{ 
    clock_t elapsed, pause, stamp; 
    stamp = clock(); 
    pause = milliseconds * CLOCKS_PER_SEC/1000; 
    while ((elapsed = clock() - stamp) < pause); 
} 

int main (void) 
{ 
    delay(2000); 
    printf("1\n"); 

    delay(2000); 
    printf("2\n"); 

    delay(2000); 
    printf("3\n"); 

    return 0; 
} 

也請注意,在整數運算,我做的分割前的乘法。

0

反思您的客戶端,並使其成爲狀態機,而不是由事件引擎(如epoll(),kqueue(),select()或poll())驅動。

通常,IRC命令會生成一個回覆,但您不知道它們什麼時候到達,並且協議的設計使得您可能希望發送不是由來自服務器的數據啓動的命令。

使用延遲驗證到IRC服務器是一個沒有沒有,因爲有可以作爲認證如PING或CTCP的等等,你的暱稱正在使用等

的一部分,可以產生各種其他命令

另外,根據RFC,NICK命令必須在用戶之前先出現。一般來說,IRC服務器是寬容的,但不要認爲這是理所當然的。正如諺語所說的那樣,「在你接受的內容中要慷慨大方,在你所發的內容上要嚴格」。