1、服务器程序
#include "stdafx.h"
#include <iostream>
#include <string>
#include "UdpSocket.h" // 引入UdpSocket头文件
#include <SocketHandler.h>
#include <StdoutLog.h>
#include <math.h>
using namespace std;
// 服务端监听端口
port_t SERVER_PORT = 12345;
class MyHandler : public SocketHandler
{
public:
MyHandler(StdLog *p) : SocketHandler(p), m_done(false), m_quit(false) {}
~MyHandler() {}
void SetQuit() { m_quit = true; }
bool Quit() { return m_quit; }
void CheckHtml() {
if (m_done)
{
if (m_ok)
printf("Html OK:\n%s\n", m_html.c_str());
else
printf("Html Failed\n");
m_done = false;
}
}
std::string m_html;
bool m_ok;
bool m_done;
private:
bool m_quit;
};
class TestUdpSocket : public UdpSocket
{
public:
TestUdpSocket(ISocketHandler& h) : UdpSocket(h) {
}
void OnConnect() override{
printf("TestSocket connected, sending QUIT\n");
Send("quit\n");
}
string get_substring_cstr(const char* src, size_t target_len) {
if (src == nullptr) {
return nullptr;
}
size_t actual_len = strlen(src);
size_t len = min(target_len, actual_len);
char* result = new char[len + 1];
strncpy(result, src, len);
result[len] = '\0';
string strResult(result);
delete[] result;
return strResult; // 返回 const char*(隐式转换)
}
std::string get_ip_from_sockaddr(const struct sockaddr* addr) {
if (addr == nullptr)
{
return "";
}
if (addr->sa_family != AF_INET)
{
return "非IPv4地址";
}
const struct sockaddr_in* addr_in = reinterpret_cast<const struct sockaddr_in*>(addr);
char ip_buf[INET_ADDRSTRLEN] = { 0 };
if (inet_ntop(AF_INET, (PVOID)&addr_in->sin_addr, ip_buf, sizeof(ip_buf)) == nullptr)
{
return "IP转换失败";
}
return std::string(ip_buf);
}
// 核心回调:当Socket有可读数据时触发(非阻塞)
virtual void OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len) override
{
string strrr = get_substring_cstr(buf, len);
string strIp = get_ip_from_sockaddr(sa);
int yyy = 55;
}
void OnConnectFailed() override{
printf("TestSocket::OnConnectFailed\n");
SetCloseAndDelete();
}
void OnLine(const std::string& line) override{
printf("TestSocket: %s\n", line.c_str());
}
void OnDelete() override{
printf("TestSocket::OnDelete()\n");
}
#ifdef ENABLE_RESOLVER
void OnResolved(int id, ipaddr_t a, port_t port) override{
printf("TestSocket::OnResolved(): %d, %08x:%d\n", id, a, port);
UdpSocket::OnResolved(id, a, port);
}
#endif
};
int _tmain(int argc, _TCHAR* argv[])
{
// 1. 创建UDP Socket对象
StdoutLog log;
MyHandler h(&log);
TestUdpSocket udp_socket(h);
// 2. 绑定端口(服务端必须绑定固定端口)
if (0 != udp_socket.Bind(SERVER_PORT)) {
return -1;
}
h.Add(&udp_socket);
while (true)
{
int ret = h.Select();
if (ret < 0) {
break;
}
int yyy = 55;
}
udp_socket.Close();
return 0;
}
2、客户端程序
class MyHandler : public SocketHandler
{
public:
MyHandler(StdLog *p) : SocketHandler(p), m_done(false), m_quit(false) {}
~MyHandler() {}
void SetQuit() { m_quit = true; }
bool Quit() { return m_quit; }
void CheckHtml() {
if (m_done)
{
if (m_ok)
printf("Html OK:\n%s\n", m_html.c_str());
else
printf("Html Failed\n");
m_done = false;
}
}
std::string m_html;
bool m_ok;
bool m_done;
private:
bool m_quit;
};
class UdpClientSocket : public UdpSocket {
public:
UdpClientSocket(SocketHandler& handler)
: UdpSocket(handler)
{
}
};
void CTestUDPClientDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
StdoutLog log;
MyHandler h(&log);
UdpClientSocket udp_socket(h);
// 打开 Socket(客户端无需绑定端口,系统自动分配临时端口)
udp_socket.Open("192.168.1.101", 12345);
udp_socket.Send("hello word");
h.Release();
udp_socket.Close();
//CDialogEx::OnOK();
}