udp广播原理介绍
UDP是面向非连接的网络交互协议,在UDP交互中,存在客户端和服务端,客户端(Client)主要来发送报文,服务端(Server)接收来自客户端的报文,在进行报文交互的时候,UDP是非连接的,客户端发送一个报文到指定端口,然后服务端监听了这个端口,如果收到这个报文,然后就进行处理,如果收不到,或者因为处理报文的消息队列太大,被抛弃了,就导致服务端无法收到这个报文。给大家举个例子,敌人扔了一个手雷过来,队长喊了一声“卧倒!”,有的士兵耳朵正好听到,就立马卧倒了,有的士兵可能正在带着耳机听音乐,没听到这个“报文”,结果就。。。了,所以,UDP的广播是一种不可靠的可以一对多的网络交互。
客户端实现方法
客户端思路
1、主要利用C++的 socket 创建一个udp socket.
2、利用setsockopt() 对socket进行设置参数选项
3、创建一个struct sockaddr_in 类型的对象,并进行初始化协议类型(ipv4或ipv6)、接收地址(广播地址)和接收端口号。
4、利用 sendto() 函数将udp报文进行发送。
实现代码
client头文件
#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <strings.h>
#include <string>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
using namespace std;
class UdpClient
{
public:
UdpClient();
void Init(const int port);
void StartBroadCast(const string info);
static void* UdpBroadCast(void * arg);
private:
struct sockaddr_in m_clientAddr;
string m_sendMsg;
pthread_t m_tids;
};
#endif
client cpp文件
#include "udpclient.h"
#include <QDebug>
#include <qjsondocument.h>
#include <QJsonParseError>
#include <QFile>
#include <QJsonObject>
#include <QJsonArray>
#include <QStringLiteral>
UdpClient::UdpClient()
{
bzero(&m_clientAddr, sizeof(m_clientAddr));
m_tids = 0;
}
void UdpClient::Init(const int port)
{
m_clientAddr.sin_family = AF_INET;
m_clientAddr.sin_addr.s_addr = INADDR_BROADCAST;
m_clientAddr.sin_port = htons(port);
}
void UdpClient::StartBroadCast(string info)
{
m_sendMsg = info;
if (m_tids == 0) {
pthread_create(&m_tids, NULL, UdpBroadCast, (void *)this);
}
}
void* UdpClient::UdpBroadCast(void * arg)
{
int udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
UdpClient *udp = (UdpClient *)arg;
unsigned long addr = INADDR_BROADCAST;
while (1) {
int ret = setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST, &addr, sizeof(addr));
if (ret != 0) {
qDebug()<<"[Client] set udp client options failed";
close(udpSocket);
return NULL;
}
string sendMsg =udp->m_sendMsg;
size_t sendLen = sendto(udpSocket, udp->m_sendMsg.c_str(), udp->m_sendMsg.length(),
0, (struct sockaddr*)&udp->m_clientAddr, sizeof(udp->m_clientAddr));
if (sendLen != udp->m_sendMsg.length()) {
qDebug()<<QString("[CLIENT]send msg lenth error: src len: %1 send len: %2")
.arg(sendMsg.length()).arg((int)sendLen);
} else {
qDebug()<<"[CLIENT]send success:"<<QString::fromStdString(sendMsg);
}
sleep(5);
}
close(udpSocket);
return NULL;
}
服务端实现方法
服务端思路
1、创建struct sockaddr_in 变量,设置协议族,接收地址,接收端口。
2、创建socket 变量,设置协议族
3、bind() 函数绑定socket
4、recvfrom() 来获取当前的udp报文
实现代码
server 头文件
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <strings.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
#include <functional>
using namespace std;
typedef std::function<void(string)> Fun;
typedef void(*CallFun)(string);
class UdpServer
{
public:
UdpServer();
int Init(const int port, const Fun callbackFun = NULL);
void setCallBack(Fun func);
int startListen();
static void* recv(void *args);
private:
struct sockaddr_in m_srvAddr;
int m_udpSocket;
Fun m_msgProcFun;
};
#endif
server cpp文件
#include "udpserver.h"
#include <string.h>
#include <qdebug.h>
UdpServer::UdpServer()
{
bzero(&m_srvAddr, sizeof(m_srvAddr));
m_msgProcFun = NULL;
}
int UdpServer::Init(const int port, const Fun callbackFun)
{
m_srvAddr.sin_family = AF_INET;
m_srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
m_srvAddr.sin_port = htons(port);
m_msgProcFun = callbackFun;
return startListen();
}
int UdpServer::startListen()
{
m_udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
int ret = bind(m_udpSocket,(sockaddr*)&m_srvAddr,sizeof(sockaddr));
if (ret != 0) {
return ret;
}
pthread_t tids;
ret = pthread_create(&tids, NULL, recv, (void *)this);
if (ret != 0) {
qDebug()<<"[SERVER]create thread failed";
return ret;
}
return 0;
}
void* UdpServer::recv(void *args)
{
sockaddr_in srv_Addr;
UdpServer* udp = (UdpServer*)args;
socklen_t addr_len = sizeof(srv_Addr);
char *buff = new char[100];
while(1) {
memset(buff, 0, 100);
size_t sz = recvfrom(udp->m_udpSocket, buff, 100, 0,(struct sockaddr*)&srv_Addr,&addr_len);
qDebug()<<buff;
string data = buff;
data = data.substr(16);
if (udp->m_msgProcFun) {
udp->m_msgProcFun(data);
}
}
return NULL;
}
void UdpServer::setCallBack(Fun func)
{
m_msgProcFun = func;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)