建立簡單的客戶端-服務端通信系統

本文介紹如何使用C++編寫一個基本的客戶端-服務端通信系統。通過這個例子,你將學到如何建立TCP連接、發送和接收消息,以及如何處理多個客戶端連接。

客戶端代碼:

#include <stdio.h>       // 標準輸入輸出庫,提供基本的輸入輸出功能
#include <stdlib.h>      // 標準庫,包含了一些通用的函數和動態內存分配函數
#include <string.h>      // 字符串處理庫,提供字符串操作的各種函數
#include <unistd.h>      // Linux系統調用接口,包含了一些常用的系統調用函數
#include <arpa/inet.h>   // 提供了一些函數,用于對IPv4和IPv6地址進行轉換
#include <errno.h>       // 用于獲取錯誤碼,提供 perror 函數來輸出錯誤信息int main(int argc, char *argv[]) {if (argc != 4) {fprintf(stderr, "Usage: %s <server_ip> <server_port> <message>\n", argv[0]);return EXIT_FAILURE;}int sockfd;struct sockaddr_in servaddr;// 創建套接字if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("create socket error");return EXIT_FAILURE;}// 初始化服務器地址結構體memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(atoi(argv[2]));  // 將端口號從字符串轉換為整數// 將IP地址從字符串轉換為網絡地址if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {perror("inet_pton error");close(sockfd);return EXIT_FAILURE;}// 發起連接請求if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {perror("connect error");close(sockfd);return EXIT_FAILURE;}printf("Connected to the server. Sending message: %s\n", argv[3]);// 發送消息到服務器if (send(sockfd, argv[3], strlen(argv[3]), 0) < 0) {perror("send error");close(sockfd);return EXIT_FAILURE;}// 接收服務器的響應char buffer[1024];ssize_t recv_len = recv(sockfd, buffer, sizeof(buffer), 0);if (recv_len < 0) {perror("recv error");close(sockfd);return EXIT_FAILURE;} else if (recv_len == 0) {printf("Connection closed by the server\n");} else {buffer[recv_len] = '\0';printf("Received from server: %s\n", buffer);}// 關閉套接字close(sockfd);return EXIT_SUCCESS;
}

服務端代碼:

#include <iostream>     // 輸入輸出流庫,提供了輸入輸出的各種功能
#include <cstring>      // 字符串處理庫,提供了字符串操作的各種函數
#include <thread>       // 多線程支持庫,用于創建和管理線程
#include <vector>       // 動態數組容器,提供了對動態數組的支持
#include <mutex>        // 互斥鎖庫,提供了對互斥鎖的支持
#include <queue>        // 隊列容器,提供了對隊列的支持
#include <netinet/in.h> // 網絡編程庫,包含了與網絡相關的數據結構和函數
#include <unistd.h>     // Linux系統調用接口,包含了一些常用的系統調用函數const int MAXBUFF = 1024;std::mutex g_mx; // 用于保護共享資源的互斥鎖
std::queue<std::pair<int, std::string>> g_dataQue; // 存儲客戶端套接字和消息的隊列// 在單獨的線程中處理從客戶端接收到的消息
void writeThread() {while (true) {g_mx.lock(); // 上鎖以確保安全訪問共享資源if (!g_dataQue.empty()) {int clientFd = g_dataQue.front().first;std::string data = g_dataQue.front().second;std::cout << "從客戶端接收到的消息:" << data << std::endl;// 假設有一個處理消息并返回響應的函數std::string response = "Server response: 你好,客戶端!";send(clientFd, response.c_str(), response.size(), 0);g_dataQue.pop(); // 從隊列中移除已處理的消息}g_mx.unlock(); // 解鎖}
}int main() {int listenFd, clientFd;struct sockaddr_in servaddr;if ((listenFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {std::cerr << "創建套接字錯誤" << std::endl;return -1;}memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(1121);if (bind(listenFd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {std::cerr << "綁定套接字地址和端口錯誤" << std::endl;return -1;}if (listen(listenFd, 10) < 0) {std::cerr << "開啟監聽錯誤" << std::endl;return -1;}std::thread write_thread(writeThread); // 創建一個線程來處理從客戶端接收到的消息size_t readLen = 0;while (true) {struct sockaddr_in client_addr;socklen_t size = sizeof(client_addr);if ((clientFd = accept(listenFd, (struct sockaddr *)&client_addr, &size)) < 0) {std::cerr << "建立連接錯誤" << std::endl;return -1;}// 假設有一個讀取函數來從 clientFd 中讀取數據char buff[MAXBUFF] = {0};readLen = read(clientFd, buff, MAXBUFF);if (readLen <= 0) {close(clientFd); // 在讀取到數據后關閉客戶端連接break;}std::string data(buff, readLen);g_mx.lock(); // 上鎖以確保安全訪問共享資源g_dataQue.push(std::make_pair(clientFd, data)); // 將接收到的消息和客戶端套接字放入隊列g_mx.unlock(); // 解鎖}write_thread.join(); // 等待寫線程結束close(listenFd);return 0;
}

客戶端使用方法:

打開終端,進入客戶端代碼所在的目錄。使用以下命令運行客戶端程序:

gcc client.cpp -o client
./client <server_ip> <server_port> <message>

替換 <server_ip><server_port><message> 分別為服務器的IP地址、端口號和要發送的消息。

服務端使用方法:

打開終端,進入服務端代碼所在的目錄。使用以下命令編譯并運行服務端程序:

g++ server.cpp -o server -lpthread
./server

服務端將開始監聽連接。

主要功能:

客戶端:

  • 接受命令行參數,包括服務器IP、端口號和要發送的消息。
  • 創建套接字,連接到服務器。
  • 發送消息到服務器,接收并打印服務器的響應。

客戶端界面

Connected to the server. Sending message: 你好,服務器!
Received from server: Server response: 你好,客戶端!

服務端:

  • 創建套接字,綁定地址和端口,開始監聽。
  • 接受客戶端連接,將客戶端套接字和消息放入隊列。
  • 在單獨的線程中處理隊列中的消息,發送響應到客戶端。

服務端界面

從客戶端接收到的消息:你好,服務器!

注意事項:

  • 通過互斥鎖保護共享資源,確保線程安全的訪問。
  • 在服務端中,處理客戶端消息后返回一個固定的響應。

結論:

通過這個簡單的例子,你學到了如何使用C++創建一個基本的客戶端-服務端通信系統。這是一個基礎框架,可以根據實際需求進行擴展和改進,用于構建更復雜的網絡應用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/162484.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/162484.shtml
英文地址,請注明出處:http://en.pswp.cn/news/162484.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

matlab使用scatter函數畫圖時報錯“數組索引必須為正整數或邏輯值”解決辦法

一、背景 在使用matlab的scatter函數畫圖時報錯“數組索引必須為正整數或邏輯值”。 scatter函數說明&#xff1a;scatter(x,y) 在向量 x 和 y 指定的位置創建一個包含圓形標記的散點圖。 二、解決辦法 如果使用scatter函數時報上述錯誤&#xff0c;嘗試將連續函數先轉換為函…

ubuntu編譯sqlite3并使用

SQLite3是一種輕量級的關系型數據庫管理系統&#xff0c;它是在C語言基礎上實現的。SQLite3具有許多優點&#xff0c;例如&#xff1a; 1.靈活&#xff1a;它可以在多種操作系統上運行&#xff0c;并且可以將多個數據庫文件合并成一個文件。 2.易于使用&#xff1a;SQLite3使用…

基于爬行動物算法優化概率神經網絡PNN的分類預測 - 附代碼

基于爬行動物算法優化概率神經網絡PNN的分類預測 - 附代碼 文章目錄 基于爬行動物算法優化概率神經網絡PNN的分類預測 - 附代碼1.PNN網絡概述2.變壓器故障診街系統相關背景2.1 模型建立 3.基于爬行動物優化的PNN網絡5.測試結果6.參考文獻7.Matlab代碼 摘要&#xff1a;針對PNN神…

八股文面試day6

什么是代理&#xff1f;為什么要用動態代理&#xff1f; 代理模式大概意思是&#xff1a;為其他對象提供一個代理項或者是占位符&#xff0c;以控制對這個對象的訪問 代理模式核心思想&#xff1a;創建一個代理對象&#xff0c;在客戶端和目標對象之間的一個中介&#xff0c;…

35的程序員被辭了可以自己接外包啊?為什么都那么悲觀呢?

35的年紀&#xff0c;上有老下有小&#xff0c;即將步入中年危機&#xff0c;在這個節骨眼上被辭&#xff0c;能不悲觀嗎&#xff1f; 在這個年紀人們往往追求的是穩定的工作和生活&#xff0c;而進入一個自己不熟悉的行業并不是一個好的選擇。 況且&#xff0c;你認為的外包…

診斷0x27服務解密文件DLL制作與使用

DLL文件在CANoe的使用方法 DLL文件在診斷里面可以用在0x27秘鑰服務里面&#xff0c;對解密有幫助&#xff0c;在下圖位置加載。 DLL文件制作 vector公司本來就給了我們一個demo&#xff0c;先拷貝一份下來&#xff0c;別把原來的文件給改壞了。我這個是CANoe12&#xff0c;de…

Visio給立方體的每條邊填充不同的顏色,超好用的visio小技巧~

Visio給立方體的每條邊填充不同的顏色&#xff0c;超好用的visio小技巧~ 如何實現立方體的填充顏色從左邊的純色到右邊的多色呢&#xff1f;一起學起來吧~ 在visio中繪制一個普通的立方體&#xff1b; 用一個大的矩形蓋住剛才繪制的立方體&#xff1b; 全選之后找到 開發工具-&…

matplotlib

設置中文字體&#xff0c;圖片大小&#xff0c;分辨率&#xff0c;中文負號 符號 x軸和y軸 設置x軸和y軸的刻度 字體大小 線條樣式 繪制多個線條 圖例 顯示每個坐標值 gca 分辨率 畫布尺寸 創建圖形對象 不能直接使用區域對象作畫 繪制多子圖 均等的劃分畫布 柱狀圖 同一位置多…

Python 讀取2進制bin文件

pip下載hexdump pip install hexdump讀取bin文件 python -m hexdump xxx.bin

HTTP/HTTPS

HTTP/HTTPS 簡介 HTTP 協議是 Hyper Text Transfer Protocol&#xff08;超文本傳輸協議&#xff09;的縮寫&#xff0c;是用于從萬維網&#xff08; WWW:World Wide Web &#xff09;服務器傳輸超文本到本地瀏覽器的傳送協議。 HTTP 是一個基于 TCP/IP 通信協議來傳遞數據&a…

最新版車牌號正則效驗

支持最新版新能源、各類特種車等車牌號規則效驗 private static final Pattern pattern Pattern.compile("^([京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領A-Z]{1}[a-zA-Z](([京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊AB…

類加載過程

Java類加載過程包括加載&#xff08;Loading&#xff09;、驗證&#xff08;Verification&#xff09;、準備&#xff08;Preparation&#xff09;、解析&#xff08;Resolution&#xff09;、初始化&#xff08;Initialization&#xff09;五個階段。這些階段是按照順序逐步執…

Javascript中的宏任務與微任務

事件循環 JavaScript 語言的一大特點就是單線程&#xff0c;也就是說&#xff0c;同一個時間只能做一件事。為了協調事件、用戶交互、腳本、UI 渲染和網絡處理等行為&#xff0c;防止主線程的不阻塞&#xff0c;Event Loop 的方案應用而生。Event Loop 包含兩類&#xff1a;一…

購買Zoho CRM系統要花多少錢?

相信對CRM系統有過了解的人都知道&#xff0c;CRM系統的價格取決于功能需求&#xff0c;用戶數量&#xff0c;部署方式&#xff0c;定制開發等因素。Zoho CRM是全球領先的云CRM系統&#xff0c;自2005年推出以來&#xff0c;累計服務25萬企業&#xff0c;那么Zoho CRM系統的價格…

python批量修改文件夾下的后綴名

python批量修改文件夾下的后綴名 &#xff08;所有的.txt結尾的文件&#xff0c;替換成.py結尾&#xff09; 1、需要將某個文件夾下所有的.txt結尾的文件&#xff0c;替換成.py結尾 2、Python代碼&#xff1a; import os# 指定需要更改文件的目錄 dir_path D:/study/py/4#…

Vatee萬騰數字引領未來:vatee科技力量的獨特路徑

在當今數字化浪潮的推動下&#xff0c;Vatee萬騰以其卓越的科技力量&#xff0c;正引領著未來的數字化時代&#xff0c;描繪著一條獨特的發展路徑。通過持續創新、前瞻思維和對技術的深度理解&#xff0c;Vatee萬騰正在為未來的科技發展創造新的可能性&#xff0c;塑造著數字引…

微信開放平臺Android平臺應用簽名怎么填寫

winR 輸入cmd 進到本地簽名文件的目錄下 輸入 keytool -list -v -keystore <keystore文件路徑> -alias <別名>請將 <keystore文件路徑> 替換為您的密鑰庫文件&#xff08;通常是 .jks 或 .keystore 文件&#xff09;的路徑&#xff0c;而 <別名> 則是…

Speaker Verification,聲紋驗證詳解——語音信號處理學習(九)

參考文獻&#xff1a; Speaker Verification嗶哩嗶哩bilibili 2020 年 3月 新番 李宏毅 人類語言處理 獨家筆記 聲紋識別 - 16 - 知乎 (zhihu.com) (2) Meta Learning – Metric-based (1/3) - YouTube 如何理解等錯誤率(EER, Equal Error Rate)&#xff1f;請不要只給定義 - 知…

oracle數據庫巡檢常見腳本-系列二

簡介 作為數據庫管理員&#xff08;DBA&#xff09;&#xff0c;定期進行數據庫的日常巡檢是非常重要的。以下是一些原因&#xff1a; 保證系統的穩定性&#xff1a;通過定期巡檢&#xff0c;DBA可以發現并及時解決可能導致系統不穩定的問題&#xff0c;如性能瓶頸、資源利用率…

libcurl curlcode 35問題解決

libcurl code 35 定義&#xff1a; SSL CONNECT ERROR 我這里問題情況會出現以下兩種 SSL證書認證&#xff0c;可以添加相應的頭取消或是添加驗證 curl_easy_setopt(curl, CURLOPT_URL, combinePath.c_str());curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);curl_easy_setop…