<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 網絡,第 4 部分:構建一個簡單的 TCP 服務器 > 原文:<https://github.com/angrave/SystemProgramming/wiki/Networking%2C-Part-4%3A-Building-a-simple-TCP-Server> ## 什么是`htons`以及何時使用? 整數可以首先表示最低有效字節或最高有效字節。只要機器本身內部一致,任何一種方法都是合理的。對于網絡通信,我們需要對商定的格式進行標準化。 `htons(xyz)`以網絡字節順序返回 16 位無符號整數'short'值 xyz。 `htonl(xyz)`以網絡字節順序返回 32 位無符號整數'long'值 xyz。 這些功能被讀作“主機到網絡”;反函數(ntohs,ntohl)將網絡有序字節值轉換為主機有序排序。那么,是主機訂購 little-endian 還是 big-endian?答案是 - 這取決于你的機器!它取決于運行代碼的主機的實際體系結構。如果體系結構恰好與網絡排序相同,那么這些函數的結果就是參數。對于 x86 機器,主機和網絡訂購 _ 與 _ 不同。 簡介:每當您讀取或寫入低級 C 網絡結構(例如端口和地址信息)時,請記住使用上述功能以確保正確轉換為/從數據庫格式轉換。否則顯示或指定的值可能不正確。 ## 用于創建服務器的“4 大”網絡呼叫是什么? 創建 TCP 服務器所需的四個系統調用是:`socket`,`bind` `listen`和`accept`。每個都有特定的目的,應按上述順序調用 端口信息(由 bind 使用)可以手動設置(許多較舊的僅使用 IPv4 的 C 代碼示例執行此操作),或使用`getaddrinfo`創建 我們以后也會看到 setsockopt 的例子。 ## 調用`socket`的目的是什么? 為網絡通信創建端點。一個新的插座本身并不是特別有用;雖然我們已經指定了數據包或基于流的連接,但它并未綁定到特定的網絡接口或端口。相反,套接字返回一個網絡描述符,可以用于以后調用 bind,listen 和 accept。 ## 調用`bind`的目的是什么 `bind`調用將抽象套接字與實際網絡接口和端口相關聯。可以在 TCP 客戶端上調用 bind,但是通常不需要指定傳出端口。 ## 調用`listen`的目的是什么 `listen`調用指定傳入的未處理連接數的隊列大小,即尚未通過`accept`分配網絡描述符的隊列大小。高性能服務器的典型值為 128 或更多。 ## 為什么服務器套接字被動? 服務器套接字不會主動嘗試連接到另一臺主機;相反,他們等待傳入的連接。此外,當對等設備斷開連接時,服務器套接字不會關閉。相反,當遠程客戶端連接時,它會立即被撞到未使用的端口號以供將來通信。 ## 調用`accept`的目的是什么 初始化服務器套接字后,服務器調用`accept`以等待新連接。與`socket` `bind`和`listen`不同,此調用將被阻止。即,如果沒有新連接,則此呼叫將阻止,并且僅在新客戶端連接時返回。 注意`accept`調用返回一個新的文件描述符。此文件描述符特定于特定客戶端。將原始服務器套接字描述符用于服務器 I / O 然后想知道為什么網絡代碼失敗是常見的編程錯誤。 ## 創建 TCP 服務器的難點是什么? * 使用被動服務器套接字的套接字描述符(如上所述) * 未指定 getaddrinfo 的 SOCK_STREAM 要求 * 無法重新使用現有端口。 * 不初始化未使用的 struct 條目 * 如果當前正在使用端口,則`bind`調用將失敗 注意,端口是每臺機器 - 不是每個進程或每個用戶。換句話說,當另一個進程正在使用該端口時,您無法使用端口 1234。更糟糕的是,端口在進程完成后默認為“綁定”。 ## 服務器代碼示例 一個工作簡單的服務器示例如下所示。請注意,此示例不完整 - 例如,它不會關閉套接字描述符,也不會釋放由`getaddrinfo`創建的內存 ```c #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <unistd.h> #include <arpa/inet.h> int main(int argc, char **argv) { int s; int sock_fd = socket(AF_INET, SOCK_STREAM, 0); struct addrinfo hints, *result; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; s = getaddrinfo(NULL, "1234", &hints, &result); if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); exit(1); } if (bind(sock_fd, result->ai_addr, result->ai_addrlen) != 0) { perror("bind()"); exit(1); } if (listen(sock_fd, 10) != 0) { perror("listen()"); exit(1); } struct sockaddr_in *result_addr = (struct sockaddr_in *) result->ai_addr; printf("Listening on file descriptor %d, port %d\n", sock_fd, ntohs(result_addr->sin_port)); printf("Waiting for connection...\n"); int client_fd = accept(sock_fd, NULL, NULL); printf("Connection made: client_fd=%d\n", client_fd); char buffer[1000]; int len = read(client_fd, buffer, sizeof(buffer) - 1); buffer[len] = '\0'; printf("Read %d chars\n", len); printf("===\n"); printf("%s\n", buffer); return 0; } ``` ## 為什么我的服務器無法重新使用該端口? 默認情況下,套接字關閉時不會立即釋放端口。相反,端口進入“TIMED-WAIT”狀態。這可能會在開發過程中導致嚴重的混淆,因為超時可能會使有效的網絡代碼看起來失敗。 為了能夠立即重新使用端口,請在綁定到端口之前指定`SO_REUSEPORT`。 ```c int optval = 1; setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); bind(.... ``` 這是[對`SO_REUSEPORT`](http://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t) 的擴展 stackoverflow 介紹性討論。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看