项目依赖头文件与库文件之后
(1)服务端
// HttpServerDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
using namespace hv;
#include <string>
#include <vector>
#include "hv/hv.h"
using namespace std;
#include "hv/UdpServer.h"
#include <iostream>
using namespace hv;
#pragma pack(push, 1)
enum PacketType {
LOGIN = 1, // 登录
LOGOUT = 2, // 退出
USER_DATA = 3 // 自定义结构体数据
};
struct LoginMsgData
{
uint32_t type;
char user[32];
char pwd[32];
};
struct LogoutMsgData
{
uint32_t type;
int nId;
};
// 主机字节序 → 网络字节序
static inline uint32_t hton_u32(uint32_t value) {
return htonl(value);
}
static inline uint32_t get_u32(const void* data) {
return ntohl(*(const uint32_t*)data);
}
map<int, string> mapClientUser;
int main(int argc, char* argv[]) {
int port = 8080;
UdpServer srv;
int bindfd = srv.createsocket(port);
if (bindfd < 0) {
return -20;
}
printf("server bind on port %d, bindfd=%d ...\n", port, bindfd);
srv.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
uint32_t type = get_u32(buf->data());
switch (type)
{
case LOGIN:
{
mapClientUser[channel->fd()] = channel->peeraddr();
printf("< 唯一标识:%d - ip地址:%s\n", channel->fd(),
channel->peeraddr().c_str());
if (buf->size() < sizeof(LoginMsgData)) return;
LoginMsgData* pkt = (LoginMsgData*)buf->data();
channel->write("login success");
break;
}
case LOGOUT:
{
printf("< 唯一标识:%d - ip地址:%s\n", channel->fd(),
channel->peeraddr().c_str());
if (buf->size() < sizeof(LogoutMsgData)) return;
channel->write("logout success");
auto itrFind = mapClientUser.find(channel->fd());
if (itrFind != mapClientUser.end())
{
mapClientUser.erase(itrFind);
}
break;
}
default:
{
printf("❌ 未知包类型\n");
break;
}
}
};
srv.start();
std::string str;
while (std::getline(std::cin, str)) {
if (str == "close") {
srv.closesocket();
}
else if (str == "start") {
srv.start();
}
else if (str == "stop") {
srv.stop();
break;
}
else {
srv.sendto(str);
}
}
return 0;
}
#pragma pack(pop)
(2)客户端
#include "hv/UdpClient.h"
#include <iostream>
#include <string>
#pragma pack(push, 1)
using namespace std;
using namespace hv;
enum PacketType {
LOGIN = 1, // 登录
LOGOUT = 2, // 退出
USER_DATA = 3 // 自定义结构体数据
};
struct LoginMsgData
{
uint32_t type;
char user[32];
char pwd[32];
};
struct LogoutMsgData
{
uint32_t type;
int nId;
};
static inline uint32_t hton_u32(uint32_t value) {
return htonl(value);
}
static inline uint32_t get_u32(const void* data) {
return ntohl(*(const uint32_t*)data);
}
int main(int argc, char* argv[]) {
int remote_port = 8080;
const char* remote_host = "127.0.0.1";
UdpClient cli;
int sockfd = cli.createsocket(remote_port, remote_host);
if (sockfd < 0) {
return -20;
}
printf("client sendto port %d, sockfd=%d ...\n", remote_port, sockfd);
cli.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
printf("< %s\n", (char*)buf->data());
};
cli.start();
{
LoginMsgData login{};
login.type = hton_u32(PacketType::LOGIN);
strcpy(login.user, "admin");
strcpy(login.pwd, "123456");
cli.sendto(&login, sizeof(login));
}
{
LogoutMsgData _logout{};
_logout.type = hton_u32(PacketType::LOGOUT);
_logout.nId = 123;
cli.sendto(&_logout, sizeof(_logout));
}
std::string str;
while (std::getline(std::cin, str)) {
if (str == "close") {
}
else if (str == "start") {
}
else if (str == "stop") {
}
else {
}
}
return 0;
}
#pragma pack(pop)
至此,一个简单的udp服务器端与客户端的demo完成
