日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程套接字(四)

發(fā)布時間:2024/4/11 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程套接字(四) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

網(wǎng)絡(luò)編程套接字(四)

文章目錄

  • 網(wǎng)絡(luò)編程套接字(四)
    • 一、實現(xiàn)tcp服務(wù)器多用戶版本(多進程、多線程、線程池版本)

一、實現(xiàn)tcp服務(wù)器多用戶版本(多進程、多線程、線程池版本)

  • tcp_process_server.hpp
#pragma once #include "tcp_socket.hpp" #include <functional> #include <signal.h>typedef std::function<void (const std::string& req,std::string* resp)> Handler;class TcpProcessServer {public:TcpProcessServer(const std::string& ip,uint16_t port):ip_(ip),port_(port){//對于多進程版本服務(wù)器,在請求到來時生成子進程處理請求,父進程繼續(xù)accept。如果父進程不等待//子進程結(jié)束,子進程將成為僵尸進程(zombie)從而占用系統(tǒng)資源。如果父進程等待子進程結(jié)束//將增加父進程的負擔(dān),影響服務(wù)器進程的并發(fā)性能。在Linux下可以簡單地將 SIGCHLD信號的操作設(shè)為SIG_IGN。//將SIGCHLD(子進程結(jié)束自動像父進程發(fā)送的信號)此信號設(shè)為忽略SIG_IGNsignal(SIGCHLD,SIG_IGN);}void ProcessConnect(TcpSocket& new_sock,const std::string& ip,uint16_t port,Handler handler){int ret = fork();if(ret > 0){//father//父進程不需要做額外操作,只需要循環(huán)accept即可,就直接返回//此處如果采用wait操作,那么就達不到采用多進程的目的,采用多進程為了可以同時處理多個用戶//如果在此處wait,那么父進程就會等待子進程處理客戶端請求結(jié)束,特別耗費時間new_sock.Close();return;}else if(ret == 0){//child//處理具體的鏈接過程即根據(jù)請求計算響應(yīng)while(1){std::string req;bool ret = new_sock.Recv(&req);if(!ret){printf("[client %s : %d] disconnect!\n",ip.c_str(),port);exit(0);}std::string resp;handler(req,&resp);new_sock.Send(resp);printf("[client %s : %d ] req : %s, resp : %s\n",ip.c_str(),port,req.c_str(),resp.c_str());}}else{perror("fork is error");}}bool Start(Handler handler){//1. 創(chuàng)建 socket;CHECK_RET(listen_sock_.Socket());// 2. 綁定端口號CHECK_RET(listen_sock_.Bind(ip_, port_));// 3. 進行監(jiān)聽CHECK_RET(listen_sock_.Listen(5));// 4. 進入事件循環(huán)for (;;) {// 5. 進行 acceptTcpSocket new_sock;std::string ip;uint16_t port = 0;if (!listen_sock_.Accept(&new_sock, &ip, &port)) {continue;}printf("[client %s:%d] connect!\n", ip.c_str(), port);ProcessConnect(new_sock, ip, port, handler);}return true;}private:TcpSocket listen_sock_;std::string ip_;uint16_t port_; };
  • tcp_pthread_server.hpp
#pragma once #include <functional> #include <pthread.h> #include "tcp_socket.hpp"typedef std::function<void (const std::string& req, std::string* resp)> Handler;struct ThreadArg {TcpSocket new_sock;std::string ip;uint16_t port;Handler handler; };class TcpThreadServer {public:TcpThreadServer(const std::string& ip, uint16_t port) : ip_(ip), port_(port) {} bool Start(Handler handler) {// 1. 創(chuàng)建 socket;CHECK_RET(listen_sock_.Socket());// // 2. 綁定端口號CHECK_RET(listen_sock_.Bind(ip_, port_));// // 3. 進行監(jiān)聽CHECK_RET(listen_sock_.Listen(5));// 4. 進入循環(huán)for (;;) {// 5. 進行 acceptThreadArg* arg = new ThreadArg();arg->handler = handler;bool ret = listen_sock_.Accept(&arg->new_sock, &arg->ip, &arg->port);if (!ret) {continue;}printf("[client %s:%d] connect\n", arg->ip.c_str(), arg->port);// 6. 創(chuàng)建新的線程完成具體操作pthread_t tid;pthread_create(&tid, NULL, ThreadEntry, arg);pthread_detach(tid);}return true;}static void* ThreadEntry(void* arg) {ThreadArg* p = reinterpret_cast<ThreadArg*>(arg);PthreadConnect(p);// 一定要記得釋放內(nèi)存!!! 也要記得關(guān)閉文件描述符p->new_sock.Close();delete p;return NULL;}static void PthreadConnect(ThreadArg* arg) {// 1. 循環(huán)進行讀寫for (;;) {std::string req;// 2. 讀取請求bool ret = arg->new_sock.Recv(&req);if (!ret) {printf("[client %s:%d] disconnected!\n", arg->ip.c_str(), arg->port);break;}std::string resp;// 3. 根據(jù)請求計算響應(yīng)arg->handler(req, &resp);// 4. 發(fā)送響應(yīng)arg->new_sock.Send(resp);printf("[client %s:%d] req: %s, resp: %s\n", arg->ip.c_str(),arg->port, req.c_str(), resp.c_str());}}private:TcpSocket listen_sock_;std::string ip_;uint16_t port_; };
  • tcp_threadpool_server.hpp
#pragma once #include"tcp_socket.hpp" #include<pthread.h> #include"threadpool.hpp" #include<sys/syscall.h> #include<unistd.h> #include<stdio.h> #include <functional>typedef std::function<void (const std::string& req,std::string* resp)> Handler;struct Arg {TcpSocket sock_;std::string _ip;uint16_t _port;Handler _handler; };class MyTask:public Task {public:MyTask(void* arg):arg_(arg){}virtual void Run()override{Arg *arg = (Arg*)arg_;TcpSocket newsock_ = arg->sock_;std::string ArgIp = arg->_ip;int ArgPort = arg->_port;Handler ArgHandler = arg->_handler;while(1){std::string msg;int n = newsock_.Recv(&msg);if(n < 0){continue;}else if(n == 0){printf("[%s:%d]客戶端已經(jīng)關(guān)閉!\n",ArgIp.c_str(),ArgPort);break;}printf("[%s:%d]客戶端輸入:%s\n",ArgIp.c_str(),ArgPort,msg.c_str());std::string resp;ArgHandler(msg,&resp);if(newsock_.Send(resp) == false)continue;}newsock_.Close();delete arg;}private:void* arg_; };class TcpThreadPoolServer {public:TcpThreadPoolServer(const std::string ip,uint16_t port):pool(10),ip_(ip),port_(port){}~TcpThreadPoolServer(){sock_.Close();}bool Start(Handler handler){if(sock_.Socket() == false)return false;cout<<__LINE__<<endl;if(sock_.Bind(ip_,port_) == false)return false;cout<<__LINE__<<endl;if(sock_.Listen() == false)return false;while(1){Arg *NewArg = new Arg;NewArg->_handler = handler;if(sock_.Accept(&(NewArg->sock_),&NewArg->_ip,&NewArg->_port) == false)continue;printf("[%s:%d]客戶端已連接!\n",NewArg->_ip.c_str(),NewArg->_port);pool.AddTask(new MyTask((void*)NewArg));}}private:TcpSocket sock_;ThreadPool pool;std::string ip_;uint16_t port_; };

總結(jié)

以上是生活随笔為你收集整理的网络编程套接字(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。