Ai
1 Star 0 Fork 0

zc/C语言程序学习

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
UdpServer.hpp 4.81 KB
一键复制 编辑 原始数据 按行查看 历史
zc 提交于 2025-01-22 18:16 +08:00 . “json
#pragma once
#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include "Log.hpp"
// using func_t = std::function<std::string(const std::string&)>;
//std::function一个类模板,它能够存储并调用任何具有匹配签名的可调用对象(如函数)
typedef std::function<std::string(const std::string&)> func_t;
Log lg;
enum{
SOCKET_ERR=1,
BIND_ERR
};
uint16_t defaultport = 8080;
std::string defaultip = "0.0.0.0";
const int size = 1024;
class UdpServer{
public:
UdpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip)
:sockfd_(0),
port_(port),
ip_(ip),
isrunning_(false)
{}
void Init()
{
// #############################1. 创建套接字文件sockfd_###############################
sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); // PF_INET
if(sockfd_ < 0)
{
lg(Fatal, "socket create error, sockfd: %d", sockfd_);
exit(SOCKET_ERR);
}
lg(Info, "socket create success, sockfd: %d", sockfd_);
// ################################2.绑定套接字bind socket################################
//将一个地址(通常是IP地址和端口号的组合)与一个网络接口卡上的套接字(socket)关联起来。
//这样,就可以在该接口卡上使用该地址来接收和发送数据。
// struct sockaddr_in 是一个定义在 C 标准库中的结构体,用于存储与 IPv4 地址相关的网络信息。
struct sockaddr_in local;
//用于将一段内存区域清零,即将这段内存区域中sizeof(local)个字节都设置为0。
bzero(&local, sizeof(local));
//sin_family是sockaddr_in结构下的一个短整型成员, 指代协议族,在socket编程中只能是AF_INET
//选择AF_INET 的目的就是使用IPv4 进行通信。
local.sin_family = AF_INET;
//sin_port是端口号(网络字节序),需要保证我的端口号是网络字节序列,因为该端口号是要给对方发送的
local.sin_port = htons(port_);
//设置监听的IP地址,inet_addr将一个点分十进制的IP转换成一个长整型数
local.sin_addr.s_addr = inet_addr(ip_.c_str());
//1.string->uint32_t 2.uint32_t必须是网络序列的
// local.sin_addr.s_addr = htonl(INADDR_ANY);
//INADDR_ANY是一个特殊的IP地址常量,值为0x00000000,表示接受来自任何网络接口的连接。
//可以将bind函数看作一个通用的函数配接器,接受一个可调用对象,生成一个新的可调用对象。
//将local(IP地址和端口号的组合)与c创建的套接字(sockfd_)关联起来
if(bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0)
{
lg(Fatal, "bind error, errno: %d, err string: %s", errno, strerror(errno));
exit(BIND_ERR);
}
lg(Info, "bind success, errno: %d, err string: %s", errno, strerror(errno));
}
//######################运行绑定好IP、端口号等信息的套接字文件(网络接口卡)########################
void Run(func_t func) // 对代码进行分层
{
isrunning_ = true;
char inbuffer[size];
while(isrunning_)
{
struct sockaddr_in client;
// socklen_t用于指定函数参数中提供的套接字结构体中成员参数的大小
socklen_t len = sizeof(client);
//ssize_t用于表示有符号的大小或者计数,通常用于表示函数返回值、文件读写等有可能出现负数的情况
//recvfrom接收来自套接字(此处是来自client)的数据,并且适用于面向无连接的协议
ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&client, &len);
if(n < 0)
{
lg(Warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));
continue;
}
// inbuffer存储了recvfrom接收到的数据
inbuffer[n] = 0;
std::string info = inbuffer;
std::string echo_string = func(info);
//指向一指定目的地(client)发送(echo_string)中的数据
sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (const sockaddr*)&client, len);
}
}
~UdpServer()
{
if(sockfd_>0) close(sockfd_); //析构,此处就是关闭创建的套接字文件(网络接口卡)让其停止运行
}
private:
int sockfd_; // 网路文件描述符
std::string ip_; // 任意地址bind 0
uint16_t port_; // 表明服务器进程的端口号
bool isrunning_;//判断是否正常运行
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/zc-creat/c-language-program-learning.git
git@gitee.com:zc-creat/c-language-program-learning.git
zc-creat
c-language-program-learning
C语言程序学习
master

搜索帮助