#pragma once
#include "err.hpp"
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
namespace ns_server
{
const static uint16_t default_port = 8080;
class UdpServer
{
public:
UdpServer(uint16_t port = default_port) : port_(port)
{
std::cout << "server addr: " << port_ << std::endl;
}
void InitServer()
{
// 1. 创建socket接口,打开网络文件
sock_ = socket(AF_INET, SOCK_DGRAM, 0); // AF_INET 网络通信 SOCK_DGRAM UDP服务器
if (sock_ < 0)
{
std::cerr << "create socket error: " << strerror(errno) << std::endl;
exit(SOCKET_ERR);
}
std::cout << "create socket success: " << sock_ << std::endl; // 3
// 2. 给服务器指明IP地址和端口号Port
struct sockaddr_in local; // 这个 local 在哪里定义呢?用户空间的特定函数的栈帧上,不在内核中!
bzero(&local, sizeof(local)); // 清空上述字段ud
local.sin_family = AF_INET; // PF_INET 初始化socketaddr_in结构
local.sin_port = htons(port_); // 本地主机序列构建的port_,需要从主机序列转变成网络序列
// inet_addr: 1,2
// 1. 字符串风格的IP地址,转换成为4字节int, "1.1.1.1" -> uint32_t -> 能不能强制类型转换呢?不能,这里要转化
// 2. 需要将主机序列转化成为网络序列
// 3. 云服务器,或者一款服务器,一般不要指明某一个确定的IP -- 服务器可能有多张网卡,可能配有多个IP
local.sin_addr.s_addr = INADDR_ANY; // 让我们的udpserver在启动的时候,bind本主机上的任意IP
// 这里需要将字符串转换uint32_t的类型,并且同时进行将主机序列转换成网络序列
if (bind(sock_, (struct sockaddr*)&local, sizeof(local)) < 0)
{
std::cerr << "bind socket error: " << strerror(errno) << std::endl;
exit(BIND_ERR);
}
std::cout << "bind socket success: " << sock_ << std::endl; //3
}
void Start()
{
// 服务器的正常工作
char buffer[1024];
while (true)
{
// 收
// ssize_t 实际写入的大小 recvfrom(int sockfd 绑定的套接字, void *buf 接受数据存放的缓冲区, size_t len 缓冲区长度, int flags 读取方式(0), struct sockaddr *src_addr 需要知道client的IP和PORT 输入接收缓冲区, socklen_t *addrlen 实际结构体的大小); 输入输出型参数 需要知道谁发的数据
struct sockaddr_in peer;
socklen_t len = sizeof(peer); // 这里一定要写清楚,未来传入的缓冲区的大小
int n = recvfrom(sock_, buffer, sizeof(buffer)-1/*因为这是以字符作为消息的类型,所以缓冲区预留一部分空间*/, 0, (struct sockaddr*)&peer, &len); // 消息的类型需要程序员来定义
if (n > 0) buffer[n] = '\0';
else continue;
// 提取client信息
std::string clientip = inet_ntoa(peer.sin_addr); // 把一个四字节的IP转化为字符串
uint16_t clientport = ntohs(peer.sin_port); // 将从网络中获取的端口号转换成主机
std::cout << clientip << "-" << clientport << "#" << buffer << std::endl;
// 发
sendto(sock_, buffer, strlen(buffer), 0, (struct sockaddr*)&peer, len); // 往文件中去写的时候,不需要携带\0
}
}
~UdpServer()
{}
private:
int sock_;
uint16_t port_;
std::string ip_; // 后面需要去掉这个ip
};
}
网络编程套接字 - UDP套接字
146 浏览量
2023-07-18
15:11:25
上传
评论
收藏 18KB ZIP 举报
zhh601
- 粉丝: 182
- 资源: 6
最新资源
- #P0015. 全排列 超级简单
- pta题库答案c语言之排序4统计工龄.zip
- pta题库答案c语言之树结构7堆中的路径.zip
- pta题库答案c语言之树结构3TreeTraversalsAgain.zip
- pta题库答案c语言之树结构2ListLeaves.zip
- pta题库答案c语言之树结构1树的同构.zip
- 基于C++实现民航飞行与地图简易管理系统可执行程序+说明+详细注释.zip
- pta题库答案c语言之复杂度1最大子列和问题.zip
- 三维装箱问题(Three-Dimensional Bin Packing Problem,3D-BPP)是一个经典的组合优化问题
- 以下是一些关于Linux线程同步的基本概念和方法.txt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈