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

C++——NetWork

1.network.h

#include <iostream>
#include <winsock2.h>
#include <cstring>

class NetWork 
{
    int type;           // 通信协议类型
    int sock_fd;        // socket 描述符
    sockaddr_in addr; // 通信地址
    int addrlen;  // 通信地址字节数
    bool issvr;         // 是否是服务器
        // 关闭 socket 套接字并释放内存
public:
    NetWork(void);
    NetWork(int type,  const char* ip, short port, bool issvr=false);
    ~NetWork(void);
    bool open(void);

    // 等待连接,只有TCP协议的服务器才能调用
    NetWork* accept_nw(void);

    // 具备 send 和 sendto 的功能
    int send_nw(const char*buf,int flag = 0);
    int send_nw(const void* buf, size_t len,int flag = 0);

    // 具备 recv 和 recvfrom 的功能
    int recv_nw(void* buf, size_t len,int flag = 0);

    
};

 2.network.cpp

#include "network.h"
#include <iostream>
#include <stdexcept>

NetWork::NetWork(void)
{
    addrlen = sizeof(addr);
    type = SOCK_STREAM;
    issvr = false;
}

NetWork::NetWork(int type, const char* ip,short port, bool issvr):type(type),issvr(issvr)
{   
    //不在构造函数中创建socket,因为socket创建可能失败,而构造函数是没有返回值的,不能在此创建
    
    // 初始化地址结构体
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip);
    addrlen = sizeof(addr);
}

NetWork::~NetWork(void) 
{
    closesocket(sock_fd);
}

bool NetWork::open(void)
{
    //创建socket对象
    sock_fd = socket(AF_INET,type,0);
    if(sock_fd < 0)
    {
        perror("socket");
        return false;
    }
    //根据type和issvr执行以下流程
    if (issvr) 
    {
        // 服务器端绑定和监听
        if (bind(sock_fd, (sockaddr*)&addr, addrlen)) 
        {
            perror("bind");
            return false;
        }     
        if (type == SOCK_STREAM && listen(sock_fd, 50))
        {
           perror("listen");
           return false;
        }
    }
     else if (type == SOCK_STREAM && connect(sock_fd,(sockaddr*)&addr,addrlen)) 
    {
        perror("connect");
        return false;
    }
    return true;
}

NetWork* NetWork::accept_nw() 
{
    if (type != SOCK_STREAM || !issvr) 
    {
        puts("只有type为SOCK_STREAM 且为服务端才能调用该函数\n");
    }

    NetWork* nw = new NetWork;
    nw->sock_fd = accept(sock_fd, (sockaddr*)&nw->addr, &nw->addrlen);

    if (nw->sock_fd < 0) 
    {
        delete nw;
        perror("accept");
        return NULL;
    }

    return nw;
}

int NetWork::send_nw(const char* buf,int flag )
{
    if(type == SOCK_STREAM)
        return ::send(sock_fd,buf,strlen(buf)+1,flag);
    else
        return sendto(sock_fd,buf,strlen(buf)+1,flag,(sockaddr*)&addr,addrlen);
}

int NetWork::send_nw(const void* buf, size_t len,int flag )
{
    if (type == SOCK_DGRAM) 
    {
        return sendto(sock_fd, (char*)buf, len, flag, (sockaddr*)&addr, addrlen);
    } 
    else 
    {
        return send(sock_fd,(char*)buf, len, flag);
    }
}

int NetWork::recv_nw(void* buf, size_t len,int flag ) 
{
    if (type == SOCK_DGRAM) 
    {
        return recvfrom(sock_fd, (char*)buf, len, flag, (sockaddr*)&addr, &addrlen);
    } 
    else 
    {
        return recv(sock_fd, (char*)buf, len, flag);
    }
}

NetWork已经封装好了下面来使用

server.cpp

#include "network.h"
#include <Windows.h>
#include <pthread.h>
#include <cstdlib>
#include <cstring>
 using namespace std;

#define buf_size (4096)
void* server(void* arg)
{
    NetWork* cnw = static_cast<NetWork*>(arg);
    char* buf = new char[buf_size];
    for (;;)
    {
        //接收请求
        int ret = cnw->recv_nw(buf, buf_size);
        if (ret <= 0 || 0 == strcmp("quit", buf))
        {
            printf("客户端%d退出\n", cnw);
            delete cnw;
            delete buf;
            return NULL;
        }
        printf(" recv:%s bits:%d\n",  buf, ret);
        //响应请求
        strcat(buf, "::return");
        ret = cnw->send_nw(buf);
        if (ret <= 0)
        {
            printf("客户端退出\n");
            delete cnw;
            delete buf;
            return NULL;
        }
    }
    //关闭

    pthread_exit(NULL);
    
}

int main(int argc,const char * argv[])
{
    if(argc!=3)
    {
        printf("参数格式输入错误:./server + ip + port\n");
        return 0;
    }
    
    NetWork * snw = new NetWork(SOCK_STREAM,argv[1],atoi(argv[2]),true);
    if(!snw->open())
    {
       delete snw;
       return -1;
    }
    for(;;)
    {
        NetWork * cnw = snw->accept_nw();
        if(cnw ==NULL)
        {
            continue;
        }
        pthread_t tid;
        pthread_create(&tid, NULL, server, (void*)cnw);
      
        // 分离线程,让线程结束后自动回收资源
        pthread_detach(tid);
    }

}

client.cpp:不要需要开多线程,服务器开多线程因为,服务器要处理多用户发来的请求

#include "network.h"
#include <Windows.h>
#include <pthread.h>
#include <cstdlib>
#include <cstring>
 using namespace std;

#define buf_size (4096)

int main(int argc,const char * argv[])
{
    if(argc!=3)
    {
        printf("参数格式输入错误:./server + ip + port\n");
        return 0;
    }

    NetWork * cnw = new NetWork(SOCK_STREAM,argv[1],atoi(argv[2]));
    if(!cnw->open())
    {
       delete cnw;
       return -1;
    }
   
    char* buf = new char[buf_size];
    for (;;)
    {
        cout<< "<<<"<<endl;
        cin.getline(buf, buf_size);
        //发送请求
       int   ret = cnw->send_nw(buf);
        if (ret <= 0)
        {
            printf("客户端退出\n");
            delete cnw;
            delete buf;
            return 0;
        }
        //接收请求
         ret = cnw->recv_nw(buf, buf_size);
        if (ret <= 0 || 0 == strcmp("quit", buf))
        {
            printf("客户端%d退出\n", cnw);
            delete cnw;
            delete buf;
            return 0;
        }
        printf(" recv:%s bits:%d\n",  buf, ret);
     
    }
    //关闭
      
    
    }


http://www.kler.cn/news/362570.html

相关文章:

  • 干货|基于React和xlsx库导出表格数据到excel(前端操作)
  • C语言预处理详细过程
  • Java项目-基于springboot框架的疫苗接种管理系统项目实战(附源码+文档)
  • console.log(“res.data = “ + JSON.stringify(res.data));
  • 1.2 C++内存
  • 【报错处理】MR/Spark 使用 BulkLoad 方式传输到 HBase 发生报错: NullPointerException
  • Mac 使用 zsh 终端提示 zsh: killed 的问题
  • 微信小程序设置弹框底下内容不能移动 滚动(滚动穿透问题)
  • 【鼠鼠学AI代码合集#8】线性神经网络
  • Vue封装组件并发布到npm仓库
  • 【ROS2】Qt和ROS混合编程:多继承QObject和rclcpp::Node
  • LRU算法
  • ATmega128定时器里面的定时器和外部中断配置
  • ElasticSearch基本概念
  • 微软主动出击,“钓”出网络钓鱼者
  • 关于在ubuntu服务器上无法守护长链接命令的问题
  • 自动化数据库管理:如何通过存储过程动态创建 MySQL 对象
  • Python中的字符串修剪:strip()、lstrip() 和 rstrip()
  • 1U服务器和Hyper-V虚拟机使用记录
  • [Linux网络编程]06-I/O多路复用策略---select,poll分析解释,优缺点,实现IO多路复用服务器
  • 设计模式基础知识以及典型设计模式总结(上)
  • Spring Boot驱动的汽车销售网站架构优化
  • ansible playbooks
  • 关于WPF项目降低.Net版本
  • Unity性能优化2【脚本篇】
  • 电脑改ip地址怎么弄?一键操作与多种方法详解