2017-11-30 11 views
0

私はクライアントからのGETリクエストを提供するC言語の基本ウェブサーバを実装しました。問題は、HTMLページを送信しないことです。 CウェブサーバからウェブブラウザへHTMLページを送る方法

while(1){ 
     if((temp_sock[id] = accept(sockfd, (t_sockaddr*)address, &address_size))==-1){ 
      perror("Accepting Failure: "); 
      pthread_mutex_lock(&lock); 
      fprintf(logfile, "Accepting error: %d\n", localfd); 
      pthread_mutex_unlock(&lock); 
      exit(1); 
     } 
     else{ 
      pthread_mutex_lock(&lock); 
      fprintf(logfile, "\nAccepting Success"); 
      pthread_mutex_unlock(&lock); 
     } 

     if (temp_sock[id]> 0){ 
      pthread_mutex_lock(&lock); 
      fprintf(logfile, "\nClient is connected"); 
      pthread_mutex_unlock(&lock); 
     } 

     recv(temp_sock[id] , buf, buffsize, 0); 

     pthread_mutex_lock(&lock); 
     fprintf(logfile, "\nyou recieved : %s\n ", buf); 
     pthread_mutex_unlock(&lock); 

     if((resource=analyze(buf))==NULL){ /*analyze - implements basic security and searches files on a disc*/ 
      printf("\nres is NULL"); 
      write(temp_sock[id], "HTTP/1.1 200 OK\n", 16); 
      write(temp_sock[id], "Content-length: 50\n", 19); 
      write(temp_sock[id], "Content-Type: text/html\n\n", 25); 
      write(temp_sock[id], "<html><body><H1>404 Not Found</H1></body></html>", 50); 
     } 
     else{ 
      while(fgets(message, 150, resource)!=NULL){ 
       write(temp_sock[id], "HTTP/1.1 200 OK\n", 16); 
       write(temp_sock[id], "Content-length: 151\n", 19); 
       write(temp_sock[id], "Content-Type: text/html\n\n", 25); 
       write(temp_sock[id], message, 151); //here problems start 
      } 
     fclose(resource); 
     } 
     close(temp_sock[id]); 
    } 
} 

この

はちょうど私は、テキストの複数行(例えばWikipediaの記事)を含むページを送信する場合、すべてが時点まで正常に動作しますので、私は、全体のコードをポストいけない、糸のループを受け入れていますファイルを読み込もうとすると、Webサーバーはただ停止します。しかし、ファイルにのみ

<html><body><H1>Hello! How are you?</H1></body></html> 

サーバーが適切な方法でそれを送信する場合。 ありがとうございます。

答えて

4

はあなたのコードで複数の問題がありますが、最も深刻な問題はここにある:

while(fgets(message, 150, resource)!=NULL){ 
    write(temp_sock[id], "HTTP/1.1 200 OK\n", 16); 
    write(temp_sock[id], "Content-length: 151\n", 19); 
    write(temp_sock[id], "Content-Type: text/html\n\n", 25); 
    write(temp_sock[id], message, 151); //here problems start 
} 
  1. fgets()は文字列のみで正常に動作します。画像などのバイナリデータを読み取るときに正しく動作しません。代わりにfread()を使用してください。引数を少し並べ替える必要があります。

  2. HTTPのレスポンスラインは、\r\nで終わらなければならず、\nで終わる必要があります。 (これは問題の原因ではありませんが、とにかく修正する必要があります)。送信する151のContent-Lengthは偽りです。ファイルの実際のサイズを確認するか(例えば、fstat()を使用)、それを送信するか、Content-Lengthをまったく送信しないでください。必須ではありません。

  3. あなたのコードは、それよりも多くのバイトを書き込みます。戻り値をfgets()から保存し、それをwrite()に渡します。

  4. お客様のコードは、戻り値をwrite()からチェックしていません。 read()のように、write()は常にあなたが入力したすべてのデータを書き込むと仮定するのは安全ではありません。部分書き込みを実行するか、完全に失敗する可能性があります。

  5. あなたのコードは、読み込んだデータブロックごとに新しいHTTPヘッダーを送信しています。そのコードをループの外側に移動します。

+0

[OK]を、おかげで、私は約500行を含む内部の記事とページを持っている場合、私は割り当て、その後、一度にすべてを送信すべきかそれを部品に分けることはできますか? – TeamBeam

+0

@TeamBeamそれはあなた次第です。ただし、複数の書き込みに分割する場合は、より大きなバッファサイズを使用します。これは150バイトではなく、64 KBのオーダーで行われます。 – duskwuff

+1

@TeamBeamでは、クライアントに、(一度だけ送信する)ヘッダー内のファイルの全体サイズを伝え、サーバーに適したブロックサイズでデータを読み取り、送信します。クライアントは、1MBファイルを500個の2KBブロックとして読み込むことを知る必要はなく、1MBが到着したストリームだけが表示されます。 – lockcmpxchg8b

0

私は、主な問題は、あなたがHTTPヘッダーを複数回送信することだと思います。 @duskwuffで言及した問題に加えて、あなたはあなたのループに変更する必要があり

write(temp_sock[id], "HTTP/1.1 200 OK\n", 16); 
write(temp_sock[id], "Content-length: 151\n", 19); ///here still is a problem mentioned above 
write(temp_sock[id], "Content-Type: text/html\n\n", 25); 
while((currLen=fgets(message, 150, resource))!=0){ 

    write(temp_sock[id], message, currLen); 
} 
+0

これは、私が言及した問題の一つでした。最後の箇条書きを参照してください。 – duskwuff

+0

申し訳ありませんが、あなたが正しいです。私はなぜそれを見ていないのか分からない:( –

関連する問題