2017-10-19 33 views
1

我剛剛開始了一項任務,我必須創建一個處理http請求的簡單服務器。爲什麼我的http服務器打印出相同的字節? (C)

爲了讓我開始,我決定創建一個基本的服務器,等待連接,然後連續打印出從read()接收到的任何內容。

使用此代碼打印,我期望看到有\ r純文本HTTP請求和\ n通過<\r><\n>分別爲(我在我的網頁瀏覽器訪問http://ip:port)替換爲:

char buffer[buffer_size]; 
    size_t bytes; 

    while ((bytes = read(s, buffer, buffer_size - 1)) > 0) { 
     buffer[bytes] = '\0'; 
     int i = 0; 
     while(buffer[i] != '\0') { 
     if (buffer[i] == '\n') { 
      printf("%s","<\\n>\n"); 
     } else if (buffer[i] == '\r') { 
      printf("%s","<\\r>"); 
     } else { 
      printf("%c",buffer[i]); 
     } 
     i++; 
     } 
    } 

然而,而我只是讓我的控制檯垃圾郵件交替<\r>和一些看起來像001B寫在裏面(這是我的終端http://gyazo.com/13288989dc0c1f4782052a1914eb7f84圖片的鏈接)的一個奇怪的廣場。這是我的代碼問題嗎? Mozilla是否繼續故意發送垃圾郵件?

編輯:我的所有代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

#define buffer_size 1024 


int main(int argc, char **argv) { 
    int port; 
    int client; 
    struct sockaddr_in6 my_add; 
    struct sockaddr_in6 their_add; 
    socklen_t their_add_size = sizeof(their_add); 

    if (argc != 2) { 
    printf("%s\n","Usage: ./server <port>"); 
    return -1; 
    } 

    port = atoi(argv[1]); 

    my_add.sin6_family = AF_INET6; 
    my_add.sin6_addr = in6addr_any; 
    my_add.sin6_port = htons(port); 

    int s = socket(PF_INET6, SOCK_STREAM, 0); 

    if (s < 0) { 
    printf("%s","error on socket()"); 
    return -1; 
    } 

    if (bind (s, (struct sockaddr *) &my_add, sizeof(my_add)) != 0) { 
    printf("%s","error on bind()"); 
    return -1; 
    } 

    if (listen (s, 5) != 0) { 
    printf("%s","error on listen()"); 
    return -1; 
    } 

    client = accept(s, (struct sockaddr *) &their_add, &their_add_size); 
    printf("%s","connected"); 

    char buffer[buffer_size]; 
    size_t bytes; 

    while ((bytes = read(s, buffer, buffer_size - 1)) > 0) { 
    buffer[bytes] = '\0'; 
    int i = 0; 
    while(buffer[i] != '\0') { 
     if (buffer[i] == '\n') { 
    printf("%s","<\\n>\n"); 
     } else if (buffer[i] == '\r') { 
    printf("%s","<\\r>"); 
     } else { 
    printf("%c",buffer[i]); 
     } 
     i++; 
    } 
    } 

    if (bytes != 0) { 
    printf("%s","something went wrong. bytes != 0."); 
    return -1; 
    } 

    printf("%s", "connection closed"); 
    close(s); 
    return 0; 
} 
+1

什麼調試表現在緩衝? – pm100

+0

@ pm100抱歉,我不確定你的意思?我只是基本上使用emacs作爲文本編輯器,並在終端 – toastedDeli

+2

中編譯,您應該瞭解如何在調試器下運行您的程序。在Linux上,這將是GDB,你可以暫停程序檢查數據等谷歌'開始使用GDB' – pm100

回答

4

您使用了錯誤的數據類型爲bytes變量:

read()的函數原型爲:

ssize_t read(int, void *, size_t)

但是您使用的是size_t這是無符號(ssize_t簽署

所以,如果read()曾經返回它被轉換成一個巨大的數字引起有效的無限循環負數。你

還可以簡化您的代碼:

char buffer[buffer_size]; 
ssize_t bytes; 

while ((bytes = read(s, buffer, buffer_size - 1)) > 0) { 
    // Just loop over the number of bytes we've just read 
    for (ssize_t i = 0; i < bytes; ++i) { 
     const char ch = buffer[i]; 

     // Handle `ch` 
     if (ch == '\n') { 
      printf("<\\n>\n"); 
     } else if (ch == '\r') { 
      printf("<\\r>"); 
     } else { 
      printf("%c", ch); 
     } 
    } 
} 

關於更新OP問題:

if (bytes != 0) { 
    printf("%s","something went wrong. bytes != 0."); 
    return -1; 
} 

應該是:

if (0 > bytes) { 
    printf("bytes is negative. ERRNO = %d", errno); 

    return -1; 
} 

(包括#include <errno.h>它存在。 )

在我的機器上運行你的代碼給我57這是Socket not connected所以你有你的邏輯中的另一個錯誤。

在谷歌快速搜索發現問題:

你發送到監聽套接字,當你要發送到 接受/連接的一個。

Source

所以不是:

while ((bytes = read(s, buffer, buffer_size - 1)) > 0) { 

您應該使用:

while ((bytes = read(client, buffer, buffer_size - 1)) > 0) { 

因爲你想從連接的客戶端client,不是你的監聽套接字s閱讀。

這修正了我的機器上的問題:

./a.out 1337 
connectedGET/HTTP/1.1<\r><\n> 
Host: localhost:1337<\r><\n> 
Connection: keep-alive<\r><\n> 
Cache-Control: max-age=0<\r><\n> 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36<\r><\n> 
Upgrade-Insecure-Requests: 1<\r><\n> 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8<\r><\n> 
Accept-Encoding: gzip, deflate, br<\r><\n> 
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4<\r><\n> 
Cookie: TripmanagerHighlightedParameter_index=flow_l_h<\r><\n> 
<\r><\n> 
+0

我剛剛改變了我的代碼,現在當我嘗試,我退出while循環沒有打印任何東西,我的下一個檢查失敗(bytes!= 0) – toastedDeli

+0

您可以將您的代碼發佈到pastebin嗎? – d3L

+0

我編輯我的帖子,包括我所有的代碼 – toastedDeli

相關問題