1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计

这篇具有很好参考价值的文章主要介绍了1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目完整版在:

一、socket模块:套接字模块

1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计,CodeCrafters,c++,服务器,开发语言

二、提供的功能

Socket模块是对套接字操作封装的一个模块,主要实现的socket的各项操作。

socket 模块:套接字的功能
创建套接字
绑定地址信息
开始监听
向服务器发起连接
获取新连接
接受数据
发送数据
关闭套接字
创建一个监听链接
创建一个客户端连接
设置套接字选项——开启地址端口重用!
设置套接字阻塞属性——设置为非阻塞!

三、实现思想

(一)功能

对socket套接字的操作进行封装。文章来源地址https://www.toymoban.com/news/detail-728986.html

(二)意义

对socket套接字的操作进行封装。

(三)功能设计

  1. 创建套接字
  2. 绑定地址信息
  3. 开始监听
  4. 向服务器发起连接
  5. 获取新连接
  6. 接受数据
  7. 发送数据
  8. 关闭套接字
  9. 创建一个监听链接
  10. 创建一个客户端连接

四、代码

#define MAX_LISTEN 1024
class Socket {
        private:
                int _sockfd;
        public:
                Socket() :_sockfd(-1) {}
                Socket(int fd) : _sockfd(fd) {} 
                ~Socket() {Close(); }
                int fd() {return _sockfd;}
                // 1.创建套接字
                bool Create() {
                
                        //int socket (int domain,int type,int protocol);
                        _sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
                        if (_sockfd < 0) {
                                ERR_LOG("CREATE SOCKET FAILED !!");
                                return false;
                        }
                        return true;
                } 
                // 2.绑定地址信息
                bool Bind(const std::string &ip,uint16_t port) {
	       
                        struct sockaddr_in addr;
                        addr.sin_family = AF_INET;
                        addr.sin_port = htons(port);
                        addr.sin_addr.s_addr = inet_addr(ip.c_str());
                        socklen_t len = sizeof(struct sockaddr_in);
                        // int bind(int sockfd,struct sockaddr * addr,socklen_t len);
                        int ret = bind(_sockfd,(struct sockaddr*)&addr,len);
                        if (ret < 0) {
                                ERR_LOG("BIND ADDRESS FAILED!!!!");
                                return false;
                        }
                        return true;
                }
                 // 3.开始监听
                bool Listen(int backlog = MAX_LISTEN) {
                        // int listen(int backlog)
                        int ret = listen(_sockfd,backlog);
                        if (ret < 0) {
                                ERR_LOG("SOCKET LISTEN FAILED!!");
                                return false;
                        }
                        return true;
                }
                 // 4. 向服务器发起连接
                bool Connect(const std:: string& ip,uint16_t port) {
                
                        struct sockaddr_in addr;
                        addr.sin_family = AF_INET;
                        addr.sin_port = htons(port);
                        addr.sin_addr.s_addr = inet_addr(ip.c_str());
                        socklen_t len = sizeof(struct sockaddr_in);
                        // int bind(int sockfd,struct sockaddr * addr,socklen_t len);
                        int ret = connect(_sockfd,(struct sockaddr*)&addr,len);
                        if (ret < 0) {
                                ERR_LOG("CONNECT ADDRESS FAILED!!!!");
                                return false;
                        }
                        return true;
                } 
                // 5. 获取新连接
                int Accept() {
                
                        // int accept(int sockfd,struct sockaddr* addr,socklen_t *len) /
                        int newfd = accept(_sockfd,NULL,NULL);
                        if (newfd < 0) {
                                ERR_LOG("SOCKET ACCEPT FAILED!!!!");
                                return false;
                        }
                        return newfd;
                }
                ssize_t Recv(void *buf,size_t len,int flag = 0){
                        // 6.接收数据
                        //有符号长整型 
                        //ssize_t Recv(int sockfd,void* buf,size_t len,int flag);
                        ssize_t ret = recv(_sockfd,buf,len,flag);
                        if (ret <= 0) {
                                // EAGAIN 当前socket的接收缓冲区没有数据来,在非阻塞二点情况下才会有这个错误
                                // ENTER 当前socket的阻塞等待,被信号打断了
                                if (errno == EAGAIN || errno == EINTR) {
                                        return 0; // 没收到数据
                                }
                                ERR_LOG("SOCKET RECV FAILED!!");
                                return -1; // 出错
                        }
                        return ret;
                }
                ssize_t nonBlockRecv(void* buf,size_t len) {
                        return Recv(buf,len,MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接受为非阻塞
                }
	        // 7.发送数据
                ssize_t Send(const void* buf,size_t len,int flag = 0) {
                        // ssize_t send(int sockfd,void *data,size_t len,int flag) 
                        ssize_t ret = send(_sockfd,buf,len,flag);
                        if (ret < 0) {
                                ERR_LOG("SOCKET SEND FAILED!!");
                                return -1; // 出错
                        }
                        return ret; // 实际发送数据长度!!
                }
                ssize_t nonBlockSend(void* buf,size_t len) {
                        return Send(buf,len,MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接受为非阻塞
                }
	        // 8.关闭套接字
                void Close() {
                        if (_sockfd != -1) {
                                close(_sockfd);
                                _sockfd = -1;
                        }
                
                }
	        // 9.创建一个服务端链接
                bool createServer(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false) {
                        // 1.创建套接字 2. 绑定地址 3.开始监听 4.设置非阻塞 5.启动地址重用
                        if (Create() == false) return false;
                        if (Bind(ip,port) == false) return false;
                        if (Listen() == false) return false;
                       if (block_flag) NonBlock();
                        ReuseAddress();
                        return true;
                }
                // 10.创建一个客户端链接 
                bool createClient(uint16_t port, const std::string &ip) {
                        if (Create() == false) return false;
                        if (Connect(ip,port) == false) return false;
                        return true;
                }

                // 11. 设置套接字选项——开启地址端口重用!
                void ReuseAddress() {
                        // int setsockopt(int fd,int leve,int optname,void *val,int vallen)
                        int val = 1;
                        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(int));
                        val = 1;
                        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)&val, sizeof(int));
                }
                // 12. 设置套接字阻塞属性——设置为非阻塞! 
                void NonBlock() {
                        int flag = fcntl(_sockfd, F_GETFL, 0);
                        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
                }

};

五、测试

(一)tcp_cli.cc

#include "../source/server.hpp"

int main() {
    Socket cli_sock;
    cli_sock.createClient(8500,"127.0.0.1");
    std::string str = "nihao";
    cli_sock.Send(str.c_str(),str.size());
    char buf[1024] = {0};
    cli_sock.Recv(buf,1023);
    DBG_LOG("%s",buf);
    return 0;
}

(二)tcp_srv.cc

#include "../source/server.hpp"

int main() {
    Socket lst_sock;
    bool ret = lst_sock.createServer(8500);
    while (1) {
        int newfd = lst_sock.Accept();
        if (newfd < 0) {
            continue;
        }
        Socket cli_sock(newfd);
        char buf[1024] = {0};
        int ret = cli_sock.Recv(buf,1023);
            if(ret < 0) {
            cli_sock.Close();
        }
        cli_sock.Send(buf,ret);
        cli_sock.Close();
    }
    lst_sock.Close();
    return 0;
}

(三)makefile

all:client server
client:tcp_cli.cc
	g++ -std=c++11 $^ -o $@
server:tcp_srv.cc
	g++ -std=c++11 $^ -o $@

到了这里,关于1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 1.16.C++项目:仿muduo库实现并发服务器之HttpContext以及HttpServer模块的设计

    添加请求—— 处理函数映射信息(GET/POST/PUT/DELETE) 设置静态资源根目录 设置是否启动超时连接关闭 设置线程池中线程数量 启动服务器 OnConnected - 用于给TcpServer设置协议上下文 OnMessage - 用于进行缓冲区数据解析处理 获取上下文,进行缓冲区数据对象 请求的路由查 找 静态资

    2024年02月07日
    浏览(56)
  • 【项目设计】仿 muduo 库实现 OneThreadOneEventLoop 式并发服务器

    本项目主要是模仿 muduo 库实现一个以主从 Reactor 为模型,以 OneThreadOneEventLoop 为事件驱动的高并发服务器组件。通过这个服务器组件,我们可以简洁快速的搭建出一个高性能的 TCP 服务器。并且组件内部会提供不同的应用层协议支持,组件使用者可以通过这些协议快速的完成

    2024年04月23日
    浏览(68)
  • 一、C++项目:仿muduo库实现高性能高并发服务器

    仿mudou库one thread oneloop式并发服务器实现 仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器: 通过实现的高并发服务器组件,可以简洁快速的完成一个高性能的服务器搭建。并且,通过组件内提供的不同应用层协议支持,也可以快速完成一个高性能应用服务器的搭建

    2024年02月07日
    浏览(51)
  • 仿muduo库实现one thread one loop式并发服务器

      文章目录 一、项目简介 二、项目整体认识 2、1 HTTP服务器 2、2 Reactor模型 三、预备知识 3、1 C++11 中的 bind 3、2 简单的秒级定时任务实现 3、3 正则库的简单使用 3、4 通用类型any类型的实现 四、服务器功能模块划分与实现 4、1 Buffer模块 4、2 Socket模块 4、3 Channel模块 4、

    2024年04月09日
    浏览(56)
  • 从零开始实现一个C++高性能服务器框架----Socket模块

    此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 项目介绍 :实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括

    2023年04月08日
    浏览(59)
  • 网络socket服务器开发几种并发模型详解

    目录 一、socket创建流程。 二、I/O多路复用 三、服务器开发常见的并发模型 1、模型一:单线程——无IO复用 1.1 模型分析 2、模型二:单线程accept + 多线程读写业务(无IO复用) 模型分析 3、模型三:单线程多路IO复用 模型分析  4、模型四:单线程多路IO复用 + 多线程业务工作

    2024年02月11日
    浏览(38)
  • 基于muduo网络库实现的集群聊天服务器

    !!!项目是照着腾讯课堂施磊老师的视频学习,仅供个人学习记录使用!!! !!!项目是照着腾讯课堂施磊老师的视频学习,仅供个人学习记录使用!!! !!!项目是照着腾讯课堂施磊老师的视频学习,仅供个人学习记录使用!!! 使用muduo网络库搭建网络核心模块

    2024年04月26日
    浏览(39)
  • 【实战项目】c++实现基于reactor的高并发服务器

    基于Reactor的高并发服务器,分为反应堆模型,多线程,I/O模型,服务器,Http请求和响应五部分 ​全局 Channel 描述了文件描述符以及读写事件,以及对应的读写销毁回调函数,对应存储arg读写回调对应的参数 ​Channel 异或 |:相同为0,异为1 按位与:只有11为1,其它组合全部

    2024年02月12日
    浏览(53)
  • 基于多反应堆的高并发服务器【C/C++/Reactor】(中)Channel 模块的实现

    在这篇文章中虽然实现了能够和多客户端建立连接,并且同时和多个客户端进行通信。 基于多反应堆的高并发服务器【C/C++/Reactor】(上)-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/135141316?spm=1001.2014.3001.5501 但是有一个 问题(O_O)? : 这个程序它是单线程的。如果我们想

    2024年02月03日
    浏览(58)
  • C++项目——集群聊天服务器项目(一)项目介绍、环境搭建、Boost库安装、Muduo库安装、Linux与vscode配置

    今天开始想更新一个C++项目,实现一个 支持跨服务器通信、支持负载均衡的集群聊天服务器项目 。项目会应用muduo网络库、CMake编译、MySQL数据库、JSon序列化与反序列化、Redis消息订阅模式以及Nginx负载均衡功能。 有兴趣的宝可以跟我一起实操起来,巩固自己的C++学习吧~ 本项

    2024年04月14日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包