【Linux网络编程】TCP编程
00. 目錄
文章目錄
- 00. 目錄
- 01. TCP概述
- 02. TCP特點
- 03. TCP中CS架構
- 04. TCP相關函數
- 05. TCP服務端示例
- 06. TCP客戶端示例
- 07. 附錄
01. TCP概述
傳輸控制協議(TCP,Transmission Control Protocol)是一種面向連接的、可靠的、基于字節流的傳輸層通信協議,由IETF的RFC 793定義。
TCP旨在適應支持多網絡應用的分層協議層次結構。 連接到不同但互連的計算機通信網絡的主計算機中的成對進程之間依靠TCP提供可靠的通信服務。TCP假設它可以從較低級別的協議獲得簡單的,可能不可靠的數據報服務。 原則上,TCP應該能夠在從硬線連接到分組交換或電路交換網絡的各種通信系統之上操作。
02. TCP特點
TCP是一種面向廣域網的通信協議,目的是在跨越多個網絡通信時,為兩個通信端點之間提供一條具有下列特點的通信方式。
(1)基于流的方式;
(2)面向連接;
(3)可靠通信方式;
(4)在網絡狀況不佳的時候盡量降低系統由于重傳帶來的帶寬開銷;
(5)通信連接維護是面向通信的兩個端點的,而不考慮中間網段和節點。
為滿足TCP協議的這些特點,TCP協議做了如下的規定:
①數據分片:在發送端對用戶數據進行分片,在接收端進行重組,由TCP確定分片的大小并控制分片和重組;
②到達確認:接收端接收到分片數據時,根據分片數據序號向發送端發送一個確認;
③超時重發:發送方在發送分片時啟動超時定時器,如果在定時器超時之后沒有收到相應的確認,重發分片;
④滑動窗口:TCP連接每一方的接收緩沖空間大小都固定,接收端只允許另一端發送接收端緩沖區所能接納的數據,TCP在滑動窗口的基礎上提供流量控制,防止較快主機致使較慢主機的緩沖區溢出;
⑤失序處理:作為IP數據報來傳輸的TCP分片到達時可能會失序,TCP將對收到的數據進行重新排序,將收到的數據以正確的順序交給應用層;
⑥重復處理:作為IP數據報來傳輸的TCP分片會發生重復,TCP的接收端必須丟棄重復的數據;
⑦數據校驗:TCP將保持它首部和數據的檢驗和,這是一個端到端的檢驗和,目的是檢測數據在傳輸過程中的任何變化。如果收到分片的檢驗和有差錯,TCP將丟棄這個分片,并不確認收到此報文段導致對端超時并重發。
03. TCP中CS架構
基于 TCP 的網絡編程開發分為服務器端和客戶端兩部分,常見的核心步驟和流程如下:
04. TCP相關函數
4.1 socket函數
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); 功能: 創建一個套接字 參數: domain:AF_INET 這是大多數用來產生socket的協議,使用TCP或UDP來傳輸,用IPv4的地址AF_INET6 與上面類似,不過是來用IPv6的地址AF_UNIX 本地協議,使用在Unix和Linux系統上,一般都是當客戶端和服務器在同一臺及其上的時候使用 type:SOCK_STREAM 這個協議是按照順序的、可靠的、數據完整的基于字節流的連接。這是一個使用最多的socket類型,這個socket是使用TCP來進行傳輸。SOCK_DGRAM 這個協議是無連接的、固定長度的傳輸調用。該協議是不可靠的,使用UDP來進行它的連接。SOCK_SEQPACKET該協議是雙線路的、可靠的連接,發送固定長度的數據包進行傳輸。必須把這個包完整的接受才能進行讀取。SOCK_RAW socket類型提供單一的網絡訪問,這個socket類型使用ICMP公共協議。(ping、traceroute使用該協議)SOCK_RDM 這個類型是很少使用的,在大部分的操作系統上沒有實現,它是提供給數據鏈路層使用,不保證數據包的順序protocol:傳0 表示使用默認協議。 返回值:成功:返回指向新創建的socket的文件描述符,失敗:返回-1,設置errno4.2 bind函數
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 功能:將套接字與地址綁定。參數:sockfd:socket文件描述符addr:構造出IP地址加端口號addrlen:sizeof(sockaddr)長度 返回值:成功返回0,失敗返回-1, 設置errno4.3 listen函數
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int listen(int sockfd, int backlog); sockfd:socket文件描述符 backlog:排隊建立3次握手隊列和剛剛建立3次握手隊列的鏈接數和4.4 accept函數
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); sockdf:socket文件描述符 addr:傳出參數,返回鏈接客戶端地址信息,含IP地址和端口號 addrlen:傳入傳出參數(值-結果),傳入sizeof(addr)大小,函數返回時返回真正接收到地址結構體的大小 返回值:成功返回一個新的socket文件描述符,用于和客戶端通信,失敗返回-1,設置errno4.5 connect函數
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockdf:socket文件描述符 addr:傳入參數,指定服務器端地址信息,含IP地址和端口號 addrlen:傳入參數,傳入sizeof(struct sockaddr)大小 返回值:成功返回0,失敗返回-1,設置errno4.6 recv函數
ssize_t recv(int sockfd, void *buf, size_t len, int flags); 功能: 接收數據 參數:sockfd: 套接字描述符 socket的返回值或者accept返回值buf: 接收數據緩存len: buf的長度flags: 接收數據的標志, 一般默認為0返回值:成功: 實際讀到的數據的字節數, 如果對方已經關閉了 返回0表示讀到結尾失敗: -14.7 send函數
ssize_t send(int sockfd, const void *buf, size_t len, int flags); 功能: 發送數據 參數:sockfd: 套接字描述符 socket的返回值或者accept返回值buf: 發送的數據len: 發送數據的長度flags: 發送數據的標志 一般默認0 返回值:成功: 非零值 實際上發送數據的字節數失敗: -105. TCP服務端示例
server.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h>#define SIZE 128//TCP服務端 int main(void) {int ret = -1;int sockfd = -1;int connfd = -1;char buf[SIZE];struct sockaddr_in addr;struct sockaddr_in from;socklen_t len = sizeof(from);//1. 創建套接字(socket)sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return 1;}printf("sockfd = %d\n", sockfd);//2. 綁定(bind)memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(10086);inet_pton(AF_INET, "192.168.72.128", &addr.sin_addr);//綁定ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));if (-1 == ret){perror("bind");return 1;}//3. 設置監聽(listen)ret = listen(sockfd, 10);if (-1 == ret){perror("listen");return 1;}printf("服務器處于監聽狀態....\n");//4. 接受客戶端連接(accept)//sockfd 接受客戶端連接的套接字//connfd 與客戶端進行數據交互的套接字connfd = accept(sockfd, (struct sockaddr*)&from, &len);if (-1 == connfd){perror("accept");return 1;}printf("客戶端連接OK....\n");//5. 進行數據交互(read/write)while(1) {memset(buf, 0, SIZE);ret = read(connfd, buf, SIZE); if (ret <= 0){break;}printf("buf: %s\n", buf);}//6. 斷開連接(close)close(connfd);close(sockfd);return 0; }06. TCP客戶端示例
client.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h>#define SIZE 128//TCP 客戶端 int main(void) {int i = 0;int ret = -1;int sockfd = -1;char buf[SIZE];struct sockaddr_in addr;//1. 創建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == sockfd){perror("socket");return 1;}//2. 連接到服務端memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(10086);inet_pton(AF_INET, "192.168.72.128", &addr.sin_addr);ret = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));if (-1 == ret){perror("connnect");return 1;}printf("連接到服務端Ok...\n");//3. 數據交互(read/write)for (i = 0; i < 5; i++){memset(buf, 0, SIZE);sprintf(buf, "hello server %d", i);ret = write(sockfd, buf, strlen(buf));if (ret <= 0){break;}printf("send ret = %d\n", ret);sleep(1);}//4. 斷開連接close(sockfd); return 0; }07. 附錄
7.1 【Linux】一步一步學Linux網絡編程教程匯總
7.2 百度百科 TCP 傳輸控制協議
總結
以上是生活随笔為你收集整理的【Linux网络编程】TCP编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux网络编程】组播
- 下一篇: 【Linux网络编程】TCP网络编程中c