头文件包含udp通信的初始化,发送数据,开启监听线程,结束监听线程等函数的定义。
头文件引用中,Signal.h 为基于poco库编写的信号类,用于实现信号的发送与槽函数的绑定(类似QT的信号与槽效果)。此处可以不使用,将其头文件及相关的信号函数进行注释屏蔽即可。
#include
#include
#include
#include
#include
#include
#include
#include
public:
UdpSocket(/* args */);
/**
* int localPort
* int remotePort
* const char* localAddress
* const char* remoteAddress
*/
UdpSocket(int localPort, int remotePort, const char* localAddress, const char* remoteAddress);
~UdpSocket();
/**
* int localPort 本地端口
* int remotePort 目标端口
* const char* localAddress 本地IP
* const char* remoteAddress 目标IP
*/
bool init(int localPort, int remotePort, const char* localAddress, const char* remoteAddress);
/**
* const char *byteArray 待发送数据
* int length 发送数据长度
* 返回成功发送数据的长度
*/
int sendData(const char *byteArray, int length);
/**
* open listening thread 开启监听线程
*/
void udpThread();//open listening thread
/**
* close listening thread 结束监听线程
*/
void closeTread();//close listening thread
private:
bool isThreadOpen = false;//thread opening state
int socket_fd;//参数sockfd: 正在监听端口的套接口文件描述符,通过socket获得
struct sockaddr_in addr_local;//本地地址结构体
struct sockaddr_in addr_remote;//目标地址结构体
char readBuff[1024];//数据读取缓存buffer
UdpSocket::UdpSocket(/* args */){
}
//含参构造函数
UdpSocket::UdpSocket(int localPort, int remotePort, const char* localAddress, const char* remoteAddress){
//调用初始化函数
init(localPort, remotePort, localAddress, remoteAddress);
}
//销毁对象时,需要结监听线程,释放资源
UdpSocket::~UdpSocket(){
closeTread();
}
bool UdpSocket::init(int localPort, int remotePort, const char* localAddress, const char* remoteAddress){
// 1.创建一个通信的socket
/**
* AF_INET : ipv4
* SOCK_DGRAM : UDP
* return -1 : error
*/
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(socket_fd == -1) {
perror("socket");
exit(-1);
}
//local
addr_local.sin_family = AF_INET;//ipv4
addr_local.sin_port = htons(localPort);//port
addr_local.sin_addr.s_addr = inet_addr(localAddress);
//remote
addr_remote.sin_family = AF_INET;//ipv4
addr_remote.sin_port = htons(remotePort);//port
addr_remote.sin_addr.s_addr = inet_addr(remoteAddress);
// 2.绑定
int ret = bind(socket_fd, (struct sockaddr *)&addr_local, sizeof(addr_local));
if(ret == -1) {
perror("bind");
exit(-1);
}
}
/*
- sendto接口的参数:
- socket_fd: 通信的fd
- byteArray: 要发送的数据
- length: 发送数据的长度
- flags : 0
- (struct sockaddr *)&addr_remote: 通信的另外一端的地址信息
- sizeof(addr_remote): 地址的内存大小
- 返回:
-n :发送字节的数量
-0 :失败
*/
int UdpSocket::sendData(const char *byteArray, int length){
return sendto(socket_fd, byteArray, length, 0, (struct sockaddr *)&addr_remote, sizeof(addr_remote));
}
void UdpSocket::udpThread(){
isThreadOpen = true;
char ipbuf[16];
//打印本地IP和端口
printf("Server-IP : %s, Port : %d\n",
inet_ntop(AF_INET, &addr_local.sin_addr.s_addr, ipbuf, sizeof(ipbuf)),
ntohs(addr_local.sin_port));
thread serverThread(
[&]()->void
{
while (isThreadOpen)
{
//缓存buffer需要清除数据,避免数据读取时错误
memset(readBuff,0,sizeof(readBuff));
//阻塞 read and emit data
/*
- recvfrom接口的参数:
- socket_fd: 通信的fd
- readBuff: 缓存buffer
- sizeof(readBuff): 缓存buffer的长度
- flags : 0表示阻塞读取数据,MSG_DONTWAIT表示非阻塞读取数据
- NULL: 通信的另外一端的地址信息,不需要可以填NULL
- NULL: 地址的内存大小,不需要可以填NULL
- 返回:
-n :接收字节的数量
-0 :失败
*/
//接收数据与处理,可根据自己的处理方式进行调整,比如接收并打印
int length = recvfrom(socket_fd, readBuff,sizeof(readBuff), 0, NULL, NULL);
std::cout<< length <<":"<<readBuff;
}
return;
});
serverThread.detach();
}
监听线程采用detach方式(不建议join方式),通过控制标志位isThreadOpen,让线程自行判断是否结束。
void UdpSocket::closeTread(){
isThreadOpen = false;
}
#include "UdpSocket.h"
#define IP "192.168.31.190" //根据需要填写
#define localPort 4321 //根据需要填写
#define remotePort 1234 //根据需要填写
void local(){
std::cout << "local--ID:" << std::this_thread::get_id() << std::endl;
UdpSocket udp_local(localPort, remotePort, IP, IP);
udp_local.udpThread();
int i = 0;
char a[4];
a[0] = 'l';
a[1] = 'o';
a[2] = 'c';
while (i<20)
{
udp_local.sendData(a,3);
i++;
sleep(1);
}
udp_local.closeTread();
}
void remote(){
std::cout << "remote--ID:" << std::this_thread::get_id() << std::endl;
UdpSocket udp_remote(remotePort, localPort, IP,IP);
udp_remote.udpThread();
int i = 0;
char a[4];
a[0] = 'r';
a[1] = 'e';
a[2] = 'm';
while (i<20)
{
udp_remote.sendData(a,3);
i++;
sleep(1);
}
udp_remote.closeTread();
}
int main()
{
std::cout << "主线程\t";
std::cout << "main--ID:" << std::this_thread::get_id() << std::endl;
thread t_remote(remote);
thread t_local(local);
t_remote.join();
t_local.join();
std::cout << "子线程结束.\n";
return 0;
}
以上分享希望能对大家有所帮助,错误的地方欢迎留言指正,大家共同学习,共同进步。
基于linux的UDP C++ 工具类及使用完整工程:https://download.csdn.net/download/qq_40778196/87715886