0

C言語でIRCクライアントを書いています。サーバーへの接続中にいくつかの問題が発生しました。プログラムを実行すると、次のようになります。

出力

Set Fully Qualified host Domain Name(human readable):  ::automaticaly provided::

Set the port number of the server You want to connect to: ::automaticaly provided::

Destination server IP: 88.190.23.245

Socket descriptor: 3

Connection has been successfully established

Peer's IP is: 88.190.23.245
Peer's port is: 5190

:irc2.gbatemp.net NOTICE AUTH :*** Looking up your hostname...

:irc2.gbatemp.net NOTICE AUTH :*** Found your hostname (cached)

Type Your nick name: ::automaticaly provided::

Type Your user name: ::automaticaly provided::

(10-20 seconds break here and than what follows down here)


ERROR :Closing Link: thisIsMyNickNameXXXa[85.221.165.54] (Ping timeout)

temp.net NOTICE AUTH :*** Found your hostname (cached)

ERROR :Closing Link: thisIsMyNickNameXXXa[85.221.165.54] (Ping timeout)

temp.net NOTICE AUTH :*** Found your hostname (cached)

ERROR :Closing Link: thisIsMyNickNameXXXa[85.221.165.54] (Ping timeout)

temp.net NOTICE AUTH :*** Found your hostname (cached)

.......
.............
...................

================================================== ===========

::automaticaly provided::- 今のところプログラムによって渡されることを意味するので、何度も入力する必要はありません。

ところで。irc.gbatemp.net:5190 に接続しています (関連する限り、パスワードは必要ありません)

必要なデータを提供した後、10〜20秒のブレークが発生し(出力部分で指定)、エラーtemp.net部分が無限に続きます(ドットでマークしました)

したがって、問題の主な部分は、PING への応答で PONG メッセージをいつどのように送信する必要があるかということです。私は自分の研究をしましたが、まだそれを作ることができません。STDOUT に PING メッセージが表示されないのはなぜですか?

出力と PINGPONG 部分を担当するコードを以下に提供しています (コメント済み) (現在の主な問題は、エラー状態の PING TIMEOUT としての PING PONG です) おそらく while(1) ループはまだ完全ではありませんが、別のトピックの対象であると思います)以下のコード:

    int readReady=0;
    int writeReady=0;
    pid_t pID;
    char buf[1024];     //I/O buffer (?)
    pid_t sID;
    char *NICK = "NICK thisIsMyNickNameXXXa\n\r";
    char *USER = "USER tomaazrxtc 8 * :nameandsurname";
    char ping[512];
    char *change;

    pID=fork();
            if(pID < 0){
                //failed to execute fork()
                perror("Error while forking");
                getchar();getchar();
                exit(1);
            }
            if(pID > 0){
                exit(0);
                }
            //child down here
                //setting new session
                sID = setsid();
                if(sID < 0){
                    perror("Error while setting new session");
                    getchar();getchar();
                    exit(1);
                }

//---------receiving NOTICE AUTH :*** part-------------------------------

                if(recv(sockfd, buf, 1024,0)>0){
                printf(buf);
                }
                else{
                    perror("Error while receiving data");
                }

//---------providing and sending NICK and USERNAME-----------------------

                printf("Type Your nick name: \n");
                //scanf(nickname); pamietaj zeby zapewnic podawanie tylko nicku, a format handler zrobic osobno

                send(sockfd, NICK, strlen(NICK), 0);

                printf("Type Your user name: \n");
                //scanf(username); pamietaj zeby zapewnic podawanie tylko nicku, a format handler zrobic osobno

                send(sockfd, USER, strlen(USER), 0);

//--------Shoudnt I receive PING message just here ?????-----------------

                recv(sockfd, buf, strlen(buf), 0);
                printf(buf);

//--------PONG'ing function which I havent tested yet since i cant see PING message----

                recv(sockfd, ping, 512,0);
                if(strstr(ping, "PING")){
                    change = strstr(ping, "PING");
                    strncpy(change, "PONG", 4);
                    send(sockfd, ping, 512, 0);
                    }

//-------------------------------------------------------------------------


                while(1){
                    //sleep(1);
                    if((readReady = readReadiness(sockfd))==0){    //nothing to recv
                        if((writeReady = writeReadiness(sockfd))>0){  //sending is possible
                                scanf(buf);
                                send(sockfd, buf, strlen(buf), 0);
                                continue;
                        }
                        else
                            continue; //if there s no data to read and cant send (is it even possible?)
                    }
                    else{ //if there s some data to recv() on the socket buffer
                        recv(sockfd, buf, strlen(buf), 0);
                        printf(buf);
                        continue;
                    }
                }
//--------------------------------------------------------------------------

Ok。今後の質問は他の人に任せて、答えを提供します。それは些細なことでした。

USER 変数の末尾に \n\r を追加しました (NICK 文字列と同様)。魔法のようにつながる!!

やっと : ))

4

1 に答える 1

3

だから、私がすぐに見つけたいくつかの問題は次のとおりです。

  1. NICK正しく終了していません。する必要があります\r\n
  2. USERはまったく終了していません。で終わる必要があり\r\nます。
  3. ping応答を送信すると、ハードコードされたサイズは。になり512ます。send()文字列では機能しません。生データで機能します。だから、ここでもたくさんのゴミを渡すことになります。あなたはあなたが受け取ったものに基づいて長さを渡す必要があります。
  4. printf(buf);安全ではありません。たまたまフォーマット指定子を含む着信文字列は、printf()それらを解釈しようとします(これは「フォーマット文字列の脆弱性」として知られています)。printf("%s", buf);安全な方法で同じ動作を実現するには、これらをに置き換える必要があります。
  5. 一般に、コードはIRCから受信したメッセージがヌル終了していることを前提としています。ではない。の戻り値を使用して、recv()受信したデータの量を知る必要があります。
  6. strlen()バッファのサイズを決定するために使用しています。この関数は、バッファのサイズではなく、文字列の長さを計算します。sizeof代わりに演算子を使用する必要があります。
  7. scanf(buf);をすべきかわかりませんが、それはあなたが望んでいたことではないことはほぼ間違いありません。多分あなたは探していましたfgets()か?
  8. pingのrecv()呼び出しは、の呼び出しの直後に発生しますbuf。どちらがいつ、どのくらいの期間になるかをどうやって知るのですか?常に同じバッファで作業する必要があるようです。
于 2012-05-07T13:10:17.843 に答える