1

:これは宿題のプロジェクトです。残りのコードを書いてみますが、入力 URL に接続できない理由がわかりません。

入力 URL を受け取るために少し変更したスケルトン コードが与えられました。予想される使用法は次のとおりです。./a.out http://google.com

何らかの理由で接続に成功することはありません。エラーメッセージ「接続できませんでした」が常に出力されます。後で、URL からファイルを取得してローカル ディレクトリに保存する必要がありますが、それを行う方法を見つけようとします (私の推測では、recv()以下のコードと関係があると思います)。「 http://google.com 」の場合、「index.html」を取ることが期待されます。

スケルトンコードは使用されていますが、使用connect()のマニュアルページははるかに高速であるように見えますが、機能していません。それを使用してもforループを離れることはないようです(編集:接続しようとしてスタックしているように見えるため、決して離れることはありません):getaddrinfo()bind()connect()

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

int main(int argc, char** argv) {
        // Alex: Input usage (expecting one URL)
        if (argc != 2) {
                printf("Usage: ./hw1 URL\n");
                exit(1);
        }

        // Alex: Set noHttp as argv[1] and remove "http://"
        char* noHttp = argv[1];
        char http[] = "http://";
        if (strlen(noHttp) > 7 && !strncmp(noHttp, http, 7)) noHttp += 7;
        else {
                printf("Invalid URL, expecting http://host/path\n");
                exit(1);
        }
        printf("%s\n", noHttp);

        struct addrinfo hints;
        struct addrinfo* result, * rp;
        int sock_fd, s;

        // Alex: I moved assigning hints.ai_socktype after memset()
        memset(&hints, 0, sizeof(struct addrinfo));
        //hints.ai_socktype = SOCK_STREAM;

        s = getaddrinfo(noHttp, "8080", &hints, &result); // To Stack Overflow: This changed to "80", I am leaving it here because there are comments about it
        if (0 != s) {
                perror("Error populating address structure");
                exit(1);
        }

        int i = 0;
        for (rp = result; rp != NULL; rp = rp->ai_next) {
                printf("i = %d\n", i);
                i++;

                //printf("rp->ai_flags = %d\n", rp->ai_flags);
                printf("rp->ai_family = %d\n", rp->ai_family);
                printf("rp->ai_socktype = %d\n", rp->ai_socktype);
                printf("rp->ai_protocol = %d\n", rp->ai_protocol);

                sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
                printf("sock_fd = %d\n", sock_fd);
                if (sock_fd == -1) continue;

                // Success
                if (connect(sock_fd, rp->ai_addr, rp->ai_addrlen) != -1) break;
                close(sock_fd);
        }

        if (rp == NULL) {
                fprintf(stderr, "could not connect\n");
                exit(1);
        }

        freeaddrinfo(result);

        char buf[255];
        memset(&buf, 0, sizeof(buf));

        int recv_count = recv(sock_fd, buf, 255, 0);
        if (recv_count < 0) {
                perror("Receive failed");
                exit(1);
        }

        printf("%s",buf);
        shutdown(sock_fd, SHUT_RDWR);
        return 0;
}

編集:Uku Loskitが推奨"8080"するように置き換えました。"80"

4

3 に答える 3

2

あなたのプログラムは私には問題ないように見えますnetcat。ポート 8080 で実行し、ホストに接続します。

$ echo "Hello" | ncat -l 8080

戻ります:

$ gcc -Wall sample.c 
$ ./a.out http://127.0.0.1
127.0.0.1
i = 0
rp->ai_family = 2
rp->ai_socktype = 1
rp->ai_protocol = 6
sock_fd = 3
Hello
$ 

HTTP に接続するには、最初に HTTP リクエストを送信する必要があります。送信しないとブロックされます。64 行目の後に追加します。

    freeaddrinfo(result);

    send(sock_fd, "GET / HTTP/1.1\n\n", 16, 0); // HTTP request

    char buf[255];
    memset(&buf, 0, sizeof(buf));

これにより、リクエストが送信されます。

GET / HTTP/1.1

ポートを に変更すると80、動作するはずです。

$ ./a.out http://google.com
google.com
i = 0
rp->ai_family = 2
rp->ai_socktype = 1
rp->ai_protocol = 6
sock_fd = 3
HTTP/1.1 200 OK
Date: Sun, 01 Sep 2013 21:05:16 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151
$ 
于 2013-09-01T21:03:36.013 に答える
1

8080 ではなくポート 80 で接続する必要があります。ポート 80 は HTTP のデフォルトです。

于 2013-09-01T20:53:34.523 に答える