
- C++基礎
- C++主頁
- C++概述
- C++環境設定
- C++基本語法
- C++註釋
- C++ Hello World
- C++省略名稱空間
- C++常量/字面量
- C++關鍵字
- C++識別符號
- C++資料型別
- C++數值資料型別
- C++字元資料型別
- C++布林資料型別
- C++變數型別
- C++變數作用域
- C++多個變數
- C++基本輸入/輸出
- C++修飾符型別
- C++儲存類
- C++運算子
- C++數字
- C++列舉
- C++引用
- C++日期和時間
- C++控制語句
- C++決策
- C++ if 語句
- C++ if else 語句
- C++巢狀 if 語句
- C++ switch 語句
- C++巢狀 switch 語句
- C++迴圈型別
- C++ while 迴圈
- C++ for 迴圈
- C++ do while 迴圈
- C++ foreach 迴圈
- C++巢狀迴圈
- C++ break 語句
- C++ continue 語句
- C++ goto 語句
- C++建構函式
- C++建構函式和解構函式
- C++複製建構函式
C++套接字程式設計
C++套接字程式設計是使用C++在網路上建立兩個套接字之間通訊的方法。在本教程中,我們將學習使用C++中不同型別的套接字進行套接字程式設計的全部內容。
什麼是套接字?
套接字充當網路資料交換的接觸點,就像在網路上傳送和接收資料的端點一樣。它們允許應用程式使用TCP(傳輸控制協議)和UDP(使用者資料報協議)等協議相互通訊。它們是大多數網際網路通訊的基礎,因為它使我們能夠從網路瀏覽到即時聊天。
套接字有兩種型別
- 流式套接字(TCP):它提供可靠的、面向連線的通訊,其中資料以連續流的形式傳送,確保資料包按順序到達且沒有錯誤。
- 資料報套接字(UDP):它提供無連線的通訊。它獨立地以資料包的形式傳輸資料,但不保證順序或交付,使其以快速但不可靠的方式傳送。
C++中的套接字程式設計
C++中的套接字程式設計是一種強大的方法,用於建立網路應用程式,這些應用程式允許使用套接字API透過網路在裝置之間進行通訊。此過程涉及在客戶端和伺服器之間建立連線,從而能夠透過TCP或UDP等協議進行資料交換。
C++伺服器端套接字(偵聽連線)
以下方法用於處理伺服器端通訊
1. socket()
socket()是網路程式設計中的系統呼叫,它在C++中建立一個新的TCP套接字,該套接字定義在<sys/socket.h>標頭檔案中。
語法
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
其中,
- int sockfd宣告一個整數變數,該變數將儲存套接字檔案描述符。
- AF_INET表示套接字將使用IPv4地址族。
- SOCK_STREAM指定套接字將使用TCP(面向流的協議),並且
- 0允許系統為指定的地址族和套接字型別(在這種情況下為TCP)選擇預設協議。
2. bind()
bind()方法與套接字關聯,具有特定的本地地址和埠號,允許套接字偵聽該地址上的傳入連線。
語法
bind(sockfd, (struct sockaddr*)&address, sizeof(address));
其中,
- sockfd是表示程式中套接字的檔案描述符,用於執行各種套接字操作
- (struct sockaddr)&address將地址結構轉換為bind函式的通用指標型別。
- sizeof(address)指定地址結構的大小,以告知系統預期多少資料。
3. listen()
listen()函式將套接字標記為被動套接字,這準備了一個套接字以接受傳入的連線請求(對於伺服器)。
語法
listen(sockfd, 10);
其中,
- sockfd是表示程式中套接字的檔案描述符,用於執行各種套接字操作
- 10是積壓引數,它指定伺服器繁忙時可以排隊的最大待處理連線數。
4. accept()
accept()函式接受來自客戶端的新連線(對於伺服器)。它從待處理連線佇列中提取第一個連線請求,併為該連線建立一個新的套接字。
語法
int clientSocket = accept(sockfd, (struct sockaddr*)&clientAddress, &clientLen);
其中,
- sockfd:它是套接字的檔案描述符,用於執行各種套接字操作。
- (struct sockaddr)&address:這是一個型別轉換,它將clientAddress的指標型別轉換為struct sockaddr*型別的指標。
- &clientLen:它是指向一個變數的指標,該變數儲存clientAddress的大小。
C++客戶端套接字(連線到伺服器)
以下方法用於客戶端通訊
1. connect()
此函式是一個系統呼叫,它嘗試使用套接字建立與指定伺服器的連線(對於客戶端)。
語法
connect(sockfd, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
其中,
- sockfd是表示程式中套接字的檔案描述符,用於執行各種套接字操作。
- (struct sockaddr*)&serverAddress將serverAddress轉換為struct sockaddr*指標,這使得它與需要通用套接字地址型別的函式相容。
- sizeof(serverAddress)指定serverAddress的大小
2. send()
send()函式是套接字程式設計中的系統呼叫,它將資料傳送到已連線的套接字。
語法
send(sockfd, "Hello", strlen("Hello"), 0);
其中,
- sockfd是表示程式中套接字的檔案描述符,用於執行各種套接字操作。
- strlen("Hello")函式返回字串“Hello”(5個位元組)的長度,顯示要傳送多少位元組的資料。
- 0允許系統為指定的地址族和套接字型別(在這種情況下為TCP)選擇預設協議。
3. recv()
recv()函式是一個系統呼叫,用於從已連線的套接字接收資料,允許客戶端或伺服器讀取傳入的訊息。
語法
recv(sockfd, buffer, sizeof(buffer), 0);
其中,
- sockfd是表示程式中套接字的檔案描述符,用於執行各種套接字操作。
- buffer是指向記憶體位置的指標,接收到的資料將儲存在此處。此緩衝區應足夠大以容納傳入的資料。
- sizeof(buffer)指定要從套接字讀取的最大位元組數,這通常是緩衝區的大小。
關閉客戶端套接字
close()方法關閉開啟的套接字。
語法
close(sockfd);
其中,
- close函式是一個系統呼叫,它關閉與套接字關聯的檔案描述符。
套接字程式設計所需的標標頭檔案
在C或C++中使用套接字進行程式設計時,必須包含特定標標頭檔案才能進行必要的宣告。
對於Linux/Unix系統
- <sys/socket.h>
- <netinet/in.h>
- <arpa/inet.h>
- <unistd.h>
- <string.h>
- <errno.h>
對於Windows系統
- <winsock2.h>
- <ws2tcpip.h>
- <windows.h>
C++套接字程式設計示例
這是一個簡單的示例,用於說明C++中的TCP伺服器和客戶端
TCP伺服器程式碼
#include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> #include <cstring> #include <iostream> #define PORT 8080 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; // Create socket server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Attach socket to the port setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // Bind if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // Listen if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // Accept a connection new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen); if (new_socket < 0) { perror("accept"); exit(EXIT_FAILURE); } // Read data read(new_socket, buffer, 1024); std::cout << "Message from client: " << buffer << std::endl; // Close socket close(new_socket); close(server_fd); return 0; }
TCP客戶端程式碼
#include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> #include <cstring> #include <iostream> #define PORT 8080 int main() { int sock = 0; struct sockaddr_in serv_addr; const char *hello = "Hello from client"; // Create socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { std::cerr << "Socket creation error" << std::endl; return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { std::cerr << "Invalid address/ Address not supported" << std::endl; return -1; } // Connect to server if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { std::cerr << "Connection Failed" << std::endl; return -1; } // Send data send(sock, hello, strlen(hello), 0); std::cout << "Message sent" << std::endl; // Close socket close(sock); return 0; }
編譯和執行步驟
以下是編譯和執行客戶端套接字程式的步驟
編譯伺服器和客戶端程式碼檔案
g++ -o server server.cpp g++ -o client client.cpp
執行伺服器
./server
執行客戶端(在另一個終端中)
./client
最佳實踐
- 錯誤處理:始終檢查套接字函式的返回值以正確處理錯誤。
- 阻塞與非阻塞:預設情況下,套接字以阻塞模式執行。因此,請考慮使用非阻塞套接字或多路複用(如select或poll)來處理多個連線。
- 跨平臺問題:此示例適用於Unix/Linux。對於Windows,您需要包含<winsock2.h>並使用WSAStartup()初始化Winsock。
實際應用
套接字在現實生活中的應用和工具等方面有各種應用,這裡列舉了一些。
這些示例演示瞭如何將套接字用於不同的應用程式
- 回顯伺服器:一個簡單的伺服器,它會回顯收到的訊息。
- 聊天應用程式:一個多執行緒伺服器,允許多個客戶端聊天。
- FTP客戶端/伺服器:透過網路傳輸檔案的簡單實現。
- Web伺服器:套接字處理HTTP請求和響應以提供Web內容。
- 線上多人遊戲:套接字支援玩家和遊戲伺服器之間的即時通訊。
- 遠端訪問工具:套接字提供用於遠端管理伺服器的安全連線。
- VoIP應用程式:套接字即時傳輸音訊和影片資料以進行通訊。
- 流媒體服務:套接字將連續的音訊和影片內容傳遞給使用者。
- 物聯網裝置:套接字促進智慧裝置和伺服器之間的通訊。
- 即時協作工具:套接字允許使用者之間即時共享編輯和訊息。
- 資料同步服務:套接字管理裝置和伺服器之間的檔案上傳和下載。
- 天氣監測系統:套接字將即時天氣資料傳送到中央伺服器進行分析。
- 支付處理系統:套接字安全地傳輸客戶端和銀行之間的交易資料。
- 聊天機器人:套接字能夠在對話介面中實現即時訊息傳遞和響應。