【问题标题】:IRC bot malfunctionIRC 机器人故障
【发布时间】:2017-05-13 02:46:24
【问题描述】:

我试图在 C 中创建一个 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);
            }
        }
    }
}

任何和所有的帮助将不胜感激

【问题讨论】:

  • wireshark 和调试器是您应该熟悉的工具。

标签: c network-programming bots irc


【解决方案1】:

无论可能存在什么其他问题,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;
}

还请注意,在整数算术中,我在除法之前进行乘法运算。

【讨论】:

    【解决方案2】:

    重新考虑您的客户端,使其成为状态机,而不是由事件引擎驱动,例如 epoll()、kqueue()、select() 或 poll()。

    通常,IRC 命令会生成回复,但您不知道它们何时会到达,并且该协议被设计为您可能希望发送并非由来自服务器的数据发起的命令。

    使用延迟向 IRC 服务器进行身份验证是不可以的,因为可以生成各种其他命令作为身份验证的一部分,例如 PING 或 CTCP 等,您的昵称正在使用等。

    另外,根据 RFC,NICK 命令必须在用户之前出现。通常,IRC 服务器是宽容的,但不要认为这是理所当然的。正如谚语所说,“接受的要慷慨,发送的要严格”。

    【讨论】:

      猜你喜欢
      • 2019-08-09
      • 2018-12-31
      • 1970-01-01
      • 2017-01-26
      • 2012-07-28
      • 2012-08-20
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多