網絡計算機模擬實現

今天給大家說說前幾天完成的一個模擬的網絡計算機吧,雖然計算機的模擬實現的原理很簡單,但是如果要想寫乘網絡的,個人認為是不簡單的。基本上算是包涵了套接字編程的三分之一的知識點,此處的套接字編程指的是在理解TCP/IP五層協議的基礎上,如果不算理解這些協議的話,那么我感覺實現這個,應該是包含了多半的套接字編程。下面就讓我們看看代碼吧!

#pragma once
#include <pthread.h>
#include <iostream>
#include <queue>
#include <string>
#include <semaphore.h>
#include "deal.hpp"
#define PTHREAD_NUM 6
#define TASKNUM 5template <class T>
class pthreadPool;
template <class T>
struct data
{std::string _name;pthreadPool<T> *_str;data(pthreadPool<T> *str) : _str(str){}
};
template <class T>
class pthreadPool
{
public:friend data<T>;static pthreadPool<T> *get(){return _str;}void run(const T &x, int sock){_task = x;_sock = sock;}void start(){for (size_t i = 0; i < PTHREAD_NUM; i++){data<T> *p = new data<T>(this);if (i % 2 == 0)p->_name = "product";elsep->_name = "consumer";pthread_create(tid + i, nullptr, enter, p);}std::cout << "wancheng" << std::endl;}~pthreadPool(){pthread_mutex_destroy(&_pmtx);pthread_mutex_destroy(&_cmtx);sem_destroy(&_p);sem_destroy(&_c);for (size_t i = 0; i < PTHREAD_NUM; i++)pthread_join(tid[i], nullptr);}private:int _sock = 0;T _task = T();pthread_t tid[PTHREAD_NUM];pthread_mutex_t _pmtx;pthread_mutex_t _cmtx;sem_t _p;sem_t _c;int _pp = 0;int _cc = 0;std::vector<T> _v;static pthreadPool<T> *_str;pthreadPool(){_v.resize(TASKNUM);sem_init(&_p, 0, TASKNUM);sem_init(&_c, 0, 0);pthread_mutex_init(&_cmtx, nullptr);pthread_mutex_init(&_pmtx, nullptr);}void product(const T x){// 生產數據sem_wait(&_p);pthread_mutex_lock(&_pmtx);_v[_pp++] = x;_pp = _pp % TASKNUM;_task = T();pthread_mutex_unlock(&_pmtx);sem_post(&_c);}void consumer(){T x;// 消費數據sem_wait(&_c);pthread_mutex_lock(&_cmtx);x = _v[_cc++];_cc = _cc % TASKNUM;pthread_mutex_unlock(&_cmtx);sem_post(&_p);// 處理數據deal(x, _sock);}static void *enter(void *args){data<T> *p = reinterpret_cast<data<T> *>(args);while (true){if (strcmp(p->_name.c_str(), "product") == 0 && p->_str->_task != T())p->_str->product(p->_str->_task);else if (strcmp(p->_name.c_str(), "consumer") == 0)p->_str->consumer();//std::cout << "xiuxi" << std::endl;continue;}delete p;return nullptr;}
};
template <class T>
pthreadPool<T> *pthreadPool<T>::_str = new pthreadPool<T>();
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void deal(std::string &data, int sock)
{// 反序列化std::string respon;int x = 0;int y = 0;char op = '\0';int lpos = data.find(" ");int rpos = data.rfind(" ");// std::cout<<lpos<<" "<<rpos<<std::endl;if (lpos != std::string::npos && rpos != std::string::npos){x = atoi(data.substr(lpos - 1).c_str());op = *data.substr(lpos + 1, rpos - 1).c_str();y = atoi(data.substr(rpos + 1).c_str());// std::cout<<x<<" "<<y<<" "<<op<<std::endl;}else{if (data == std::string())return;else{std::cout << "式子格式錯誤" << std::endl;exit(4);}}// 處理switch (op){case '+':respon = std::to_string(x + y);break;case '-':respon = std::to_string(x - y);break;case '*':respon = std::to_string(x * y);break;case '/':respon = std::to_string(x / y);break;default:std::cout << "計算格式錯誤" << std::endl;break;}// 關閉鏈接send(sock, respon.c_str(), respon.size(), 0);close(sock);
}
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <cstring>
#include <string>
#include "pthreadPool.hpp"
#define NUMSIZE 1024
const int listen_queue_flag = 20;
void func(pthreadPool<std::string> &pt, int sock)
{char buffer[NUMSIZE];memset(buffer, 0, NUMSIZE);ssize_t s = recv(sock, buffer, NUMSIZE, 0);std::cout << buffer << std::endl;if (s > 0){std::string bufe = buffer;pt.run(bufe, sock);}
}
// 主函數
int main(int argc, char *argv[])
{signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);if (argc != 2){std::cout << "格式錯誤" << std::endl;exit(1);}// 創建套接字int listensock = socket(AF_INET, SOCK_STREAM, 0);if (listensock < 0){std::cout << "socket enrro" << std::endl;exit(1);}// 開始綁定sockaddr_in local;local.sin_addr.s_addr = inet_addr("0.0.0.0");local.sin_family = AF_INET;local.sin_port = htons(atoi(argv[1]));int ret = bind(listensock, (sockaddr *)&local, sizeof(local));if (ret < 0){std::cout << "bind enrro" << std::endl;exit(2);}// 監聽int listens = listen(listensock, listen_queue_flag);if (listens < 0){std::cout << "listen enrro" << std::endl;exit(3);}// 建立線程池pthreadPool<std::string> *pstr = pthreadPool<std::string>::get();pstr->start();// 建立鏈接while (true){sockaddr_in client;socklen_t len = sizeof(client);int sersock = accept(listensock, (sockaddr *)&client, &len);if (sersock < 0){std::cout << "accept enrro" << std::endl;continue;}func(*pstr, sersock);}return 0;
}
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#define NUM 10
int main(int argc, char *argv[])
{if (argc != 3){std::cout << "格式錯誤" << std::endl;exit(1);}int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){std::cout << "socket enrro" << std::endl;exit(2);}sockaddr_in serve;memset(&serve, 0, sizeof(serve));serve.sin_addr.s_addr = inet_addr(argv[1]);serve.sin_family = AF_INET;serve.sin_port = htons(atoi(argv[2]));int ret = connect(sock, (sockaddr *)&serve, sizeof(serve));// std::cout<<ret<<std::endl;if (ret >= 0){// 連接成功std::string buffer;getline(std::cin, buffer);// std::cout<<buffer<<std::endl;send(sock, buffer.c_str(), buffer.size(), 0);char bufe[NUM];memset(bufe, 0, NUM);ssize_t s = recv(sock, bufe, NUM, 0);std::cout << bufe << std::endl;close(sock);}else{std::cout<<"連接錯誤"<<std::endl;exit(5);}return 0;
}

以上就是代碼,代碼量不大,但是主要是考慮的比較多。我又加了個線程池。如果是單生產者還好,但是我寫成了多生產者和多消費者,這里就有好多問題,困擾了我很久,這個計算機我大概寫了有半個月左右吧,難就難在了這個線程池的地方。下面先說說他的問題吧。

1.

首先就是我在服務端創建線程池的時候,迷糊了很久,剛開始我是在服務端創建了一個新線程,讓這個新線程去調用線程池的函數,但是后來我發現不行,因為當時我是把關閉套接字的文件寫到了服務端,這就導致一個問題,線程創建完成之后,線程池中的線程回去執行任務,但是,服務端的線程出來之后,就直接關閉文件了,導致無法發送。所以我就想了很長時間,最后把這個操作寫到了處理函數的那里,這樣就避免了連接錯誤以及服務端創建線程的問題,減少了消耗。

2.

其次而來的問題就是,因為這個線程池是多生產者多消費者的,所以我就想的是提高一點效率,攜程了可以并發執行的模型,但是問題又來了,他們怎么插入任務,要知道的是服務端可不是生產者的角色,他只是負責把讀取的人插到線程池,這就引發了一個問題,怎么插,所以我想了想,便在縣城的私有成員變量中,寫了一個任務和套接字的文件描述符。但是這樣還有問題,不知道大家注意到了我的線程池中的插入,我沒有用引用,這樣會造成拷貝構造,但是這樣可以大大降低錯誤發生概率,是的,解決不了(我沒有想到解決方法),這樣寫的目的是,在一個客戶端訪問時,我先運行run函數,然后我的生產者會插入任務,但是如果剛好在插入任務的之前,又有一個客戶端訪問時,此時的線程中的任務變量就會改變。所以我沒有用引用,這樣的話就可以在一定概率上解決這個問題,但是還是徹底解決不了。

3.

其次就是我寫的是短連接,這個可以保證多人同時訪問服務端不崩。

如果上面的實現用單生產者,多消費者的話,就可以解決,此方法如果用小伙伴知道解決的方法,希望告知,謝謝。

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

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

相關文章

泡沫玻璃市場分析:預計2028年將達到14億美元

泡沫玻璃最早是由美國匹茲堡康寧公司發明的&#xff0c;是由碎玻璃、發泡劑、改性添加劑和發泡促進劑等&#xff0c;經過細粉碎和均勻混合后&#xff0c;再經過高溫熔化&#xff0c;發泡、退火而制成的無機非金屬玻璃材料。它是由大量直徑為1~2毫米的均勻氣泡結構組成。其中吸聲…

Linux 常用命令----mktemp 命令

文章目錄 基本用法實例演示高級用法注意事項 mktemp 命令用于創建一個臨時文件或目錄&#xff0c;這在需要處理臨時數據或進行安全性測試時非常有用。使用 mktemp 可以保證文件名的唯一性&#xff0c;避免因文件名沖突而導致的問題。 基本用法 創建臨時文件: 命令 mktemp 默認…

Go語言基礎知識學習(一)

Go基本數據類型 bool bool型值可以為true或者false,例子&#xff1a; var b bool true數值型 類型表示范圍int8有符號8位整型-128 ~ 127int16有符號16位整型-32768 ~ 32767int32有符號32位整型-2147783648 ~ 2147483647int64有符號64位整型uint8無符號8位整型0 ~ 255uint16…

優思學院|如何建立公司運營指標體系?如何推行六西格瑪改進運營指標?

關鍵績效指標 (KPI) 是測量您團隊或組織朝重要商業目標進展表現如何的量化指標&#xff0c;組織會在多個層面使用 KPI&#xff0c;這視乎您想要追蹤何指標而定&#xff0c;您可以設定全組織的、特定團隊的、或甚至是個人 KPI。 良好的KPI能讓公司管理者掌握組織的營運是否進度…

使用React 18、Echarts和MUI實現溫度計

關鍵詞 React 18 Echarts和MUI 前言 在本文中&#xff0c;我們將結合使用React 18、Echarts和MUI&#xff08;Material-UI&#xff09;庫&#xff0c;展示如何實現一個交互性的溫度計。我們將使用Echarts繪制溫度計的外觀&#xff0c;并使用MUI創建一個漂亮的用戶界面。 本文…

點評項目——分布式鎖

2023.12.10 集群模式下的并發安全問題及解決 隨著現在分布式系統越來越普及&#xff0c;一個應用往往會部署在多臺機器上&#xff08;多節點&#xff09;&#xff0c;通過加鎖可以解決在單機情況下的一人一單安全問題&#xff0c;但是在集群模式下就不行了。見下圖&#xff1a…

在 Android WebView 中實現和 JavaScript 的互操作

前言 在 APP 中內嵌一個 H5 來實現特定的業務功能已經是非常成熟且常用的方案了。 雖然 H5 已經能夠實現大多數的需求&#xff0c;但是對于某些需求還是得依靠原生代碼來實現然后與 JavaScript 進行交互&#xff0c;例如我目前所負責的項目就是一個 “智能硬件” 設備&#x…

【PyTorch】卷積神經網絡

文章目錄 1. 理論介紹1.1. 從全連接層到卷積層1.1.1. 背景1.1.2. 從全連接層推導出卷積層 1.2. 卷積層1.2.1. 圖像卷積1.2.2. 填充和步幅1.2.3. 多通道 1.3. 池化層&#xff08;又稱匯聚層&#xff09;1.3.1. 背景1.3.2. 池化運算1.3.3. 填充和步幅1.3.4. 多通道 1.4. 卷積神經…

實現React18加TS,解決通用后臺管理系統,實戰方案落地有效實踐經驗

隨著前端技術的不斷發展和更新&#xff0c;使用React 18結合TypeScript&#xff08;TS&#xff09;來構建通用后臺管理系統已成為一種常見的選擇。本文將介紹如何在項目中應用React 18和TS&#xff0c;并分享一些實戰方案的有效實踐經驗。 一、搭建React 18 TS項目 首先&…

12.2每日一題(1無窮型冪指函數:二倍角公式+三部曲+等價無窮小代換(只有整體的因子不為0才能先算出來))

注意&#xff1a;求極限不能想先算哪里就先算哪里&#xff0c;只有整體的因子不為0才能先算出來&#xff0c;部分不為0不可以先算

外貿老業務也棘手的一個問題

這幾天有2個老業務都被一個類同的問題纏住了。 客戶定購了三臺車&#xff0c;由于是非常規要求所以我建議收取全款或者最少收50%的定金。但是業務員為了當月業績或者為了拿到就收了客戶20% 或者30% &#xff0c;定金收到了&#xff0c;我也不好再逼著業務員去加收定金。 訂單就…

記錄 | ubuntu上安裝fzf

在 ubuntu 上采用命令行安裝 fzf 的方式行不通 指的是采用下面的方式行不通&#xff1a; sudo apt install fzf # 行不通 sudo snap install fzf --classic # 行不通正確的安裝方式是&#xff1a; ● 到 fzf 的 git 倉庫&#xff1a;https://github.com/junegunn/fzf/re…

在高數據量中如何優化MySQL的Group by語句?

在實際開發環境中&#xff0c;MySQL的GROUP BY操作的優化需要結合具體的業務場景和數據特點。以下是一些建議&#xff0c;可以幫助你在實際開發中優化GROUP BY查詢&#xff1a; 使用合適的索引&#xff1a; 確保GROUP BY和ORDER BY中的列上存在索引。這有助于加速分組和排序操作…

計算機畢業設計 基于SpringBoot的電動車租賃系統的設計與實現 Java實戰項目 附源碼+文檔+視頻講解

博主介紹&#xff1a;?從事軟件開發10年之余&#xff0c;專注于Java技術領域、Python人工智能及數據挖掘、小程序項目開發和Android項目開發等。CSDN、掘金、華為云、InfoQ、阿里云等平臺優質作者? &#x1f345;文末獲取源碼聯系&#x1f345; &#x1f447;&#x1f3fb; 精…

場景示例:有贊商城 × 微盛企微管家,助力零售企業,實現私域運營自動化

1 場景描述 在零售行業內&#xff0c;線上渠道已經是零售行業的主要銷售渠道&#xff0c;大多數零售企業都會將產品上架到有贊商城&#xff0c;并使用微盛企微管家系統進行客戶管理和服務&#xff0c;希望能對客戶畫像進行精細化管理&#xff0c;以提升銷售和服務效率。 然而&a…

2023年最新prometheus + grafana搭建和使用+gmail郵箱告警配置

一、安裝prometheus 1.1 安裝 prometheus官網下載地址 sudo -i mkdir -p /opt/prometheus #移動解壓后的文件名到/opt/,并改名prometheus mv prometheus-2.45 /opt/prometheus/ #創建一個專門的prometheus用戶&#xff1a; -M 不創建家目錄&#xff0c; -s 不讓登錄 useradd…

女士內衣市場分析:預計2028年將達到643.08億美元

內衣 (英文名:Underwear)&#xff0c;是指貼身穿的衣物。內衣有保暖及污穢的危害作用&#xff0c;有時會被視為性征。女士內衣行業生產的主要原料是各類織布或無紡布&#xff0c;成分有海綿、邊、定型紗、骨膠、肩帶等&#xff0c;布面料在內衣企業的生產成本中所占比重較大。女…

Python基礎(四、探索迷宮游戲)

Python基礎&#xff08;四、探索迷宮游戲&#xff09; 游戲介紹游戲說明 游戲介紹 在這個游戲中&#xff0c;你將扮演一個勇敢的冒險者&#xff0c;進入了一個神秘的迷宮。你的任務是探索迷宮的每個房間&#xff0c;并最終找到隱藏在其中的寶藏。 游戲通過命令行界面進行交互…

web 前端之標簽練習+知識點

目錄 實現過程&#xff1a; 結果顯示 1、HTML語法 2、注釋標簽 3、常用標簽 4、新標簽 5、特殊標簽 6、在網頁中使用視頻和音頻、圖片 7、表格標簽 8、超鏈接標簽 使用HTML語言來實現該頁面 實現過程&#xff1a; <!DOCTYPE html> <html><head>…

泡沫包裝市場分析:預計2029年將達到659億元

泡沫包裝&#xff0c;簡單地講&#xff0c;就是用數學方法對無線電測量或光學測量所獲得的彈道數據進行檢驗、整理、校正、計算&#xff0c;減小或消除數據的誤差&#xff0c;得出反映運載火箭運動軌跡的精確彈道參數。通常所說的泡沫包裝&#xff0c;主要是指由可發性聚苯乙烯…