2016-08-08 17 views
1

サーバーに接続するクライアントソケットを作成しました。それから私はそれにHTTPリクエストを送るつもりです。HTTP要求を送信してCで応答を受け取るとセグメンテーションエラーが発生する

GET /index.html HTTP/1.1\r\n 
Host: www.google.com\r\n 
\r\n 

これは私のコードです:私はそれを実行すると

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#define MAX 4096 

int main(int argc, char **argv){ 
    char *host; 
    strcpy(host, argv[1]); 

    char *request = "GET "; 
    strcat(request, argv[3]); 
    strcat(request, " HTTP/1.1\r\nHost: "); 
    strcat(request, argv[2]); 
    strcat(request, "\r\n\r\n"); 

    char *response; 

    int port; 
    port = atoi(argv[2]); 

    int sockfd; 
    struct sockaddr_in servaddr; 
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 
      perror("Failed to create socket!"); 
      exit(1); 
    } 

    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(port); 

    struct hostent *server; 
    server = gethostbyname(host); 
    if (server == NULL) perror("Failed to get host name!"); 

    memcpy(&servaddr.sin_addr.s_addr, server->h_addr, server->h_length); 

    if(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){ 
      perror("Failed to connect!"); 
      exit(1); 
    } 

    while(fgets(request, MAX, stdin) != NULL){ 
      send(sockfd, request, strlen(request), 0); 
      if(recv(sockfd, response, MAX, 0) == 0){ 
        perror("Failed to recieve!"); 
        exit(1); 
      } 

      printf("Response:/n"); 
      fputs(response, stdout); 
    } 

は、それがセグメンテーションフォールトを得ました。それから私はGDBを使ってそれをトレースします。

#0 strcmp() at ../sysdeps/x86_64/multiarch/../strcmp.S:132 
#1 0x00007ffff7deb1a5 in _dl_name_match_p (name=0x4004e9 "libc.so.6",  map=0x7ffff7ffe1c8) at dl-misc.c:289 
#2 0x00007ffff7de402f in do_lookup_x ([email protected]=479433942, [email protected]=0x7fffffffe950, 
[email protected]=0x7fffffffe960, scope=<optimized out>, i=<optimized out>, [email protected]=0, [email protected]=1, 
[email protected]=0x0, [email protected]=0x7ffff7ffe1c8) at dl-lookup.c:462 
#3 0x00007ffff7de4961 in _dl_lookup_symbol_x (undef_name=0x40056b "strcat", undef_map=0x7ffff7ffe1c8, 
[email protected]=0x7fffffffea18, symbol_scope=0x7ffff7ffe520, version=0x7ffff7ff9a10, [email protected]=1, flags=1, 
[email protected]=0x0) at dl-lookup.c:737 
#4 0x00007ffff7de9527 in _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at ../elf/dl-runtime.c:111 
#5 0x00007ffff7df04d5 in _dl_runtime_resolve() at ../sysdeps/x86_64/dl-trampoline.S:45 
#6 0x0000000000400b18 in main() 

エラーメッセージは本当に私を混乱させました。どこで間違いを犯したのですか?文字列定数にrequestポイントとして

+0

'host'と' request'は書き込み可能なメモリバッファを指していません。 'strcpy'や' strcat'などの書き込み操作は使用できません。たとえば、 'malloc'を使ってメモリを割り当てる必要があります。 – kaylum

+0

'argv [2]'引数は、 'strcat(request、argv [2])'と 'port = atoi(argv [2]);'の二つの引数のために慎重に使用してください。 'argv [2]'はホストか 'argv [2]'はポートですか? –

答えて

1
char *request = "GET "; 
/* you can't do this */ 
strcat(request, argv[3]); 
strcat(request, " HTTP/1.1\r\nHost: "); 
strcat(request, argv[2]); 
strcat(request, "\r\n\r\n"); 

、あなたはそれに多くの文字を追加することはできません。あなたはそれのためのより多くのメモリを割り当てて、それに多くの文字列を追加する必要があります。

responseについても同様です。データを読み込む前にメモリを割り当てます。で

- 一般的に安全であることをstrncatなどの機能を使用することをお勧めしその後

strcpy(request, "GET "); 
strcat(request, argv[3]); 
strcat(request, " HTTP/1.1\r\nHost: "); 
strcat(request, argv[2]); 
strcat(request, "\r\n\r\n"); 

request = malloc(sizeof(char) * MAX); 
response = malloc(sizeof(char) * MAX); 

を追加します。

+0

ありがとうございました!本当に役に立ちます。 –

関連する問題