当前位置: 首页 > wzjs >正文

网站编程语言有哪些下载一个app

网站编程语言有哪些,下载一个app,深圳网站设计营销型,天津建设工程新希望目录 设计思路 类的设计 模块的实现 基础模块 特殊模块 集成模块 主函数 主函数实现 主函数测试 疑惑点 设计思路 Socket模块主要是对套接字的基础操作进行封装,简化我们对套接字的操作,不需要调用C的原生接口,而是以面向对象的…

目录

设计思路

类的设计 

模块的实现

基础模块

特殊模块 

集成模块 

主函数

主函数实现

主函数测试

疑惑点


设计思路

Socket模块主要是对套接字的基础操作进行封装,简化我们对套接字的操作,不需要调用C的原生接口,而是以面向对象的方式来调用。 

那么我们需要封装哪些接口呢?

  • 首先,最基础的接口,创建套接字,绑定地址信息,建立连接,开始监听,获取新连接,读取数据,写入数据,关闭套接字这几个基本功能我们还是需要提供的。
  • 其次就是两个特殊的功能: 设置套接字非阻塞,因为后续我们读取和写入都是非阻塞进行的。 还有就是设置地址信息和端口号复用,这是为了便于服务器崩溃之后能够立即以固定端口重启。
  • 还需要提供两个集成的功能,创建一个服务器连接,以及建立一个客户端连接

类的设计 

public: /*-- - 基础功能-- -*/bool Create();//创建套接字bool Bind();//绑定地址信息bool Connect();//向服务端发起连接bool Listen();//服务端开始监听int Accept();//获取客户端连接ssize_t send();//发送数据ssize_t Recv();//接收数据void close();//关闭套接字/*-- - 特殊功能-- -*/ssize_t SendNonBlock(void *buf, size_t len) // 非阻塞发送数据void SetNonBlock();//设置套接字非阻塞void SetAddrReuse();//设置地址信息和端口号复用/*-- - 整合功能-- -*/bool CreateServer();//创建一个服务器连接bool CreateClient();//创建一个客户端连接
};

模块的实现

这个模块是把服务端的Socket和客户端的Socket整合到一起了

基础模块

class Socket
{
private:int _sockfd;public:Socket() // 接收监听套接字的构造函数: _sockfd(-1){}Socket(int sockfd) // 接收客户端连接后的通信套接字: _sockfd(sockfd){}~Socket() { Close(); }/*-- - 基础功能-- -*/bool Create() // 创建套接字{_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (_sockfd < 0){ERR_LOG("Create failed");return false;}std::cout << "sockfd:" << _sockfd << std::endl;return true;}bool Bind(const string &ip, uint16_t port) // 绑定地址信息{struct sockaddr_in addr;memset(&addr, 0, sizeof addr);addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(ip.c_str());addr.sin_port = htons(port);socklen_t len = sizeof addr;int n = bind(_sockfd, (struct sockaddr *)&addr, len);if (n < 0){ERR_LOG("Bind failed");return false;}std::cout << "Bind:" << n << std::endl;return true;}bool Listen(int backlog = MAX_LISTEN) // 服务端开始监听{int n = listen(_sockfd, backlog);if (n < 0){ERR_LOG("Listen failed");return false;}std::cout << "Listen:" << n << std::endl;return true;}bool Connect(const string &ip, uint16_t port) // 向服务端发起连接{struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(ip.c_str());addr.sin_port = htons(port);socklen_t len = sizeof addr;int n = connect(_sockfd, (struct sockaddr *)&addr, len);if (n < 0){ERR_LOG("Connect failed");return false;}std::cout << "Connect:" << n << std::endl;return true;}int Accept() // 获取客户端连接{int connfd = accept(_sockfd, nullptr, nullptr);std::cout << "Accept:" << connfd << std::endl;if (connfd < 0){ERR_LOG("Accept failed");return -1;}return connfd;}ssize_t Send(const void *buf, size_t len, int flag = 0) // 将数据从用户态缓冲区发送到内核缓冲区{int n = send(_sockfd, buf, len, flag);if (n < 0){if (errno == EAGAIN || errno == EINTR){return 0;ERR_LOG("send failed");return -1;}}return n;}ssize_t Recv(void *buf, size_t len, int flag = 0) // 接收数据{int n = recv(_sockfd, buf, len, flag);if (n < 0){if (errno == EAGAIN || errno == EINTR){return 0;ERR_LOG("recv failed");return -1;}}return n;}void Close() // 关闭套接字{close(_sockfd);}ssize_t SendNonBlock(void *buf, size_t len) // 非阻塞发送数据{return Recv(buf, len, MSG_DONTWAIT);}};

特殊模块 

为什么需要把套接字设置成非阻塞属性呢?

设置非阻塞其实就两个步骤,首先获取描述符当前属性,然后再在获取到的属性上加上我们的非阻塞属性,再将其设置进描述符中。 这里需要用到 fcntl() 接口 

int fcntl(int fd, int cmd, ... /* arg */);

    man手册中说明了,获取和设置O_CLOEXEC 也就是不可被拷贝,是使用 F_GETFD和F_SETFD,而其他属性的获取和设置则需要使用F_GETFL 和 F_SETFL。

        // 设置套接字非阻塞属性void SetNonBlock(){// int fcntl(int fd, int cmd, ...)int flag = fcntl(_sockfd, F_GETFL, 0);fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);}

     地址信息和端口号复用需要用到的 setsockopt()  接口

    int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
    

    第一个参数就是要设置的文件描述符或者说套接字,第二个参数就是要设置的层级,第三个参数表示要进行什么操作,第四个参数表示要设置的值,1 表示激活,0表示取消,第四个参数表示第三个参数的大小。

        void SetAddrReuse() // 设置地址信息和端口号复用{int val = 1;int ret = setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &val, sizeof val);// 设置 SO_REUSEADDR 可以绑定处于 TIME_WAIT 状态的端口// 设置 SO_REUSEPORT 可以让一个端口被多个 socket 绑定,可以用于实现负载均衡}

    集成模块 

    然后就是设计两个集成端口,首先创建服务器套接字,他需要创建一个套接字绑定端口和IP设置非阻塞,还要设置地址复用,以及开始监听。 

        bool CreateServer(uint16_t port, const string &ip = "0.0.0.0", bool nonblock = false) // 创建一个服务器连接{// 1.创建套接字 2.绑定地址 3.开始监听 4.打开地址重用 5.设置非阻塞if (Create() == false)return false;if (Bind(ip, port) == false)return false;if (Listen() == false)return false;SetAddrReuse();if (nonblock)SetNonBlock();return true;}

    而建立一个客户端套接字,他也需要创建套接字,但是它不需要我们显式绑定端口和IP,然后就是调用Conect进行连接服务器。注意客户端套接字不要connect之前设置非阻塞,因为如果设置了非阻塞,那么我们就无法判断connect是否连接成功。

        bool CreateClient(uint16_t port, const string &ip) // 创建一个客户端连接{// 1.创建套接字 2.连接客户端if (Create() == false)return false;if (Connect(ip, port) == false)return false;return true;}

    主函数

    主函数实现

    server.cc

    #include <iostream>
    #include "Socket.hpp"#define PORT 8080int main()
    {// 创建服务端套接字Socket serverSocket;// 创建并初始化服务端if (!serverSocket.CreateServer(PORT, "0.0.0.0", true)){std::cerr << "Server initialization failed!" << std::endl;return -1;}std::cout << "Server is listening on port " << PORT << "..." << std::endl;// 接受客户端连接int clientSocket = -1;while (1){sleep(1);clientSocket = serverSocket.Accept();if (clientSocket < 0){std::cerr << "Failed to accept client connection!" << std::endl;}else{break;}}std::cout << "Client connected!" << std::endl;Socket conSocket(clientSocket);int RecvCount = 5;// 接收数据while (RecvCount){char buffer[1024] = {0};ssize_t bytesReceived = conSocket.Recv(buffer, sizeof(buffer));if (bytesReceived > 0){std::cout << "Received from client: " << buffer << std::endl;RecvCount--;}else{std::cerr << "Failed to receive data from client!" << std::endl;}sleep(1);}// 发送数据到客户端int SendCount = 5;while (SendCount){const char *response = "Hello from server!";ssize_t bytesSent = conSocket.Send(response, strlen(response));if (bytesSent > 0){std::cout << "Sent to client: " << response << std::endl;SendCount--;}else{std::cerr << "Failed to send data to client!" << std::endl;}sleep(1);}// 关闭连接serverSocket.Close();std::cout << "Server closed!" << std::endl;return 0;
    }

    client.cc 

    #include <iostream>
    #include "Socket.hpp"#define PORT 8080int main()
    {// 创建客户端套接字Socket clientSocket;// 创建并初始化客户端if (!clientSocket.CreateClient(PORT, "127.0.0.1")){std::cerr << "Client initialization failed!" << std::endl;return -1;}std::cout << "Client connected to server!" << std::endl;// 发送数据到服务端int SendCount = 5;while (SendCount){const char *message = "Hello from client!";ssize_t bytesSent = clientSocket.Send(message, strlen(message));if (bytesSent > 0){std::cout << "Sent to server: " << message << std::endl;SendCount--;}else{std::cerr << "Failed to send data to server!" << std::endl;}sleep(1);}// 接收数据从服务端int RecvCount = 5;while (RecvCount){char buffer[1024] = {0};ssize_t bytesReceived = clientSocket.Recv(buffer, sizeof(buffer));if (bytesReceived > 0){std::cout << "Received from server: " << buffer << std::endl;RecvCount--;}else{std::cerr << "Failed to receive data from server!" << std::endl;}sleep(1);}// 关闭连接clientSocket.Close();std::cout << "Client closed!" << std::endl;return 0;
    }

    主函数测试

    客户端往服务端发送数据

    Client.cc

    const char *message = "Hello from client!";

    ssize_t bytesSent = clientSocket.Send(message, strlen(message));

    这两段代码的过程如下:

    Server.CC 

    char buffer[1024] = {0};

    ssize_t bytesReceived = conSocket.Recv(buffer, sizeof(buffer));

    这两段代码的过程如下:

     服务端与客户端双向发送/接收,以及关闭

    疑惑点

    关于套接字的基础功能,为啥已经建立连接了,后面又获取连接了?

    因为你建立的连接是客户端->服务端的,而获取新连接,是指的服务端获取到了客户端的连接。 

    socket函数的用法 

    int socket(int domain, int type, int protocol);
    

    这里为啥要用到memset?

    bind函数的用法 

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    

     accept的用法

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    


     

    send的用法

    send read write接口的解释

    ssize_t send(const void* buf, size_t len, int flag = 0)  这里的buf指的是内核发送缓冲区还是用户态的输出缓冲区?

    send的sockfd参数是干嘛的

    是不是意思就是说,A与B进行通信的话 会有个sockfd1 C与D进行通信的话,会有个sockfd2?

    不是的

    但是每对通信的客户端和服务端都需要独立的套接字进行数据传输 

     send发送数据

      send发送数据指的是从用户态缓冲区发送到内核态缓冲区,并不是从客户端发送到服务端了

    这里send函数为啥不传_sockfd 

     为什么会有两个构造函数

    ​ 

    send()是把数据从用户输出缓冲区发送到内核的输出缓冲区中 这个内核的输出缓冲区是指的自己的内核缓冲区 还是对端的内核缓冲区?

    为什么Accept的返回值为-1

    因为此时客户端还没连接,但已经调用了获取客户端的接口。所以会返回-1

    CTRL + Z后,再次启动bind失败

    客户端发送了数据 但是服务端收不到数据 

    ​ 


    文章转载自:

    http://wIY1Xehw.kyjpg.cn
    http://g8oBz7wH.kyjpg.cn
    http://2WZqAW6r.kyjpg.cn
    http://j4LVbIcT.kyjpg.cn
    http://rvWz8xCQ.kyjpg.cn
    http://WUViXfzJ.kyjpg.cn
    http://DjGkHahE.kyjpg.cn
    http://7hPAlTTb.kyjpg.cn
    http://Fn0H4Dba.kyjpg.cn
    http://fbi25S2t.kyjpg.cn
    http://kbZdrnh3.kyjpg.cn
    http://Qg8pUg7w.kyjpg.cn
    http://VDWfwXT2.kyjpg.cn
    http://LVuXFSOD.kyjpg.cn
    http://R66nA8O2.kyjpg.cn
    http://D6DVqK4D.kyjpg.cn
    http://bGzZnZ3N.kyjpg.cn
    http://Mhh0O18G.kyjpg.cn
    http://AIOnBAho.kyjpg.cn
    http://9a6HLOXj.kyjpg.cn
    http://np8ZUplM.kyjpg.cn
    http://WireHGTv.kyjpg.cn
    http://iMMU6G5T.kyjpg.cn
    http://mQXCex3g.kyjpg.cn
    http://z80b6vKP.kyjpg.cn
    http://rfpVZAUv.kyjpg.cn
    http://K4ccIfD1.kyjpg.cn
    http://128pnNwz.kyjpg.cn
    http://OIMEi1nM.kyjpg.cn
    http://Jp1jRd26.kyjpg.cn
    http://www.dtcms.com/wzjs/637521.html

    相关文章:

  • php网站 更改logo网站建设制作包括哪些
  • 网站充值怎么做分录权重高的博客网站
  • 网站制作公司需要什么资质做论坛网站需要备案
  • 温州网站建设公司排名电商小程序名字大全
  • 容桂网站建设企业外包是什么意思
  • 怎么下载网站模板图书馆网站设计方案
  • 上海网站建设公司怎么分辨好坏论坛门户网站建设
  • 建网站做外贸0基础做网站
  • 舒城县建设局网站响应式网站展示型
  • 报纸门户网站建设方案php网站整合discuz
  • 企业网站制作是什么网站美工建设软件下载
  • 泌阳县住房和城乡建设局网站拓者设计吧注册码共享
  • 移动网站建设初学视频教程网站域名免费注册
  • html网站开发实例视频专门做玉的网站
  • 虚拟主机销售网站模板橙 网站
  • 旅游投资公司网站建设公众号电脑版登陆入口
  • 用网站的源代码怎么做网站有意思的网站
  • 网站如何做标题优化做网站一般不选用的图片格式
  • 乐陵市住房和城乡建设局网站typecho对比wordpress
  • 公司做竞拍网站的收入怎么报税用模板做网站需要懂代码吗
  • 客户网站开发全流程南昌房产网
  • 宁波网站建设制作推广优化网站服务
  • 天津市建设安全协会网站网店运营推广1+x证书查询
  • 企业网站如何去做优化英语字体设计网站好
  • 展示型网站搭建wordpress搬家文章
  • WordPress下拉下一页企业营销型网站seo推广
  • 开公司先建设网站外国网站欣赏
  • linux 搭建网站服务器ai海报设计
  • 湖北网站建设制作网站备案成功后该怎么做
  • 网站字体大小选择wordpress博客重装