【原】一个通用的udp收发模块(类)——针对linux或QT环境
标签:
udplinuxqt宏通用 |
分类: 软件开发 |
概述
udp收发包也是我们工程中经常用到的东西。不同的平台有不同的socket函数和接口。每次编写程序的时候还要重新写这些东西,非常繁琐。所以考虑能不能写一些公用代码来简化这部分操作。
主要针对的开发环境:
我平时面对的开发环境主要是这几种;
1) QT平台
众所周知,QT是跨平台的,所以如果开发环境有安装QT的话,一套代码就能全搞定了。QT处理udp收发包使用的是QUdpSocket类。这个类还是比较强大的。
使用bind绑定端口。 writeDatagram发数据。readDatagram收数据。
2)linux服务器
linux服务器上面有的装了QT。有的没有装。所以还需要针对linux的接口单独编码。
3)Android智能手机
谢天谢地。 android 是基于linux的,所以linux的函数它几乎都能用。
所以综上, 我只要针对两种: 装了QT环境、 以及linux环境.
所以对于没装QT的windows环境,本代码不予支持http://www/uc/myshow/blog/misc/gif/E___7380ZH00SIGG.gif
Udp收发需要用到的基本参数:
一般来说,也就这几个参数:
1) 本机地址
2) 本机端口
3) 对端地址
4) 对端端口
5) 阻塞或非阻塞(主要针对接收)
6) 数据方向(收? 发 ? 还是收发)
7) 是否支持广播
本代码中, 前四个参数都支持, 阻塞或非阻塞现在都默认为非阻塞; 数据方向支持双向, 支持广播
代码中如何区分开发环境:
一般来说,编译环境是用宏来区分的:
1)标示QT的宏:
当你执行完qmake之后,你会发现在生成的makefile文件中有这样的字样:
DEFINES
= -DUNICODE
-DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NETWORK_LIB -DQT_CORE_LIB
-DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT
-DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT
这些宏就是可以用来标识qt的。 尤其是-DQT_CORE_LIB ,qt程序都是必含的
2)标识linux的宏:
网上一搜你就容易发现:
linux的自带的系统标识宏不少: 很典型的就是 __linux__
3)综上。我们在代码中的宏判断就写成这样:
#ifdef
QT_CORE_LIB
...
#elif defined(__linux__)
...
#endif
代码:
1)
udpp.h:
#ifndef COMMONUDP_H
#define COMMONUDP_H
#include "commontypes.h"
#ifdef QT_CORE_LIB
#include ;
#endif
//模式, 0 只读,1 只写, 2 读写
typedef enum{
UDPP_READ_ONLY,
UDPP_WRITE_ONLY,
UDPP_READ_WRITE
}UDPP_RWMODE;
//阻塞和非阻塞
typedef enum{
UDPP_BLOCK,
UDPP_UNBLOCK
}UDPP_BLOCKMODE;
class Udpp
{
public:
INT m_local_port; //本机端口
INT m_dst_port; //目标端口
BYTE m_dst_addr[16]; //目标地址
INT m_socketId;
UDPP_RWMODE m_rw_mode;
UDPP_BLOCKMODE m_blockmode;
#ifdef QT_CORE_LIB
QUdpSocket m_udpSock;
#endif
public:
Udpp(BYTE *dst_addr, INT dst_port, INT local_port = 0 ,
UDPP_RWMODE rw_mode = UDPP_READ_ONLY, UDPP_BLOCKMODE blk_mode = UDPP_UNBLOCK);
~Udpp();
INT SendData(BYTE *data, INT length , BYTE* dst_addr=NULL, INT dst_port=0);
INT RecvData(BYTE *dst_data, INT max_len);
private:
Udpp(const Udpp&);
Udpp& operator= (const Udpp &);
};
#endif // COMMONUDP_H
2)
udpp.cpp
#include
#include
#ifdef QT_CORE_LIB
#include
#elif defined(__linux__)
#include
#include
#include
#include
#include
#endif
#include "udpp.h"
#include "commonlogs.h"
Udpp::Udpp(BYTE *dst_addr, INT dst_port, INT local_port,UDPP_RWMODE rw_mode,UDPP_BLOCKMODE blk_mode):
m_local_port(0),m_dst_port(0),m_rw_mode(UDPP_READ_ONLY),m_blockmode(UDPP_UNBLOCK)
{
m_local_port = local_port;
m_dst_port = dst_port;
m_rw_mode = rw_mode;
m_blockmode = blk_mode;
strcpy(m_dst_addr, dst_addr);
#ifdef QT_CORE_LIB
if(m_local_port >0 )
m_udpSock.bind(m_local_port,QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
#elif defined(__linux__)
m_socketId = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(m_local_port >0){
INT res;
struct sockaddr_in ser_addr;
ser_addr.sin_family=AF_INET;
ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);
ser_addr.sin_port=htons(local_port);
res = bind(m_socketId,(struct sockaddr*)&ser_addr,sizeof(struct sockaddr_in));
}
#endif
LOGE("socket open dst_addr[%s], dst_port[%d], local_port[%d], mode[%d]",
m_dst_addr,m_dst_port, m_local_port, m_rw_mode );
}
Udpp::~Udpp(){
#ifdef QT_CORE_LIB
; //QT析构什么都不做
#elif defined(__linux__)
shutdown(m_socketId,SHUT_RDWR); //把连接关闭
close(m_socketId);
#endif
}
int Udpp::SendData(BYTE *data, INT length, BYTE *dst_addr, INT dst_port){
if(m_rw_mode == UDPP_READ_ONLY)
return -1;
INT res=-1;
BYTE *send_to_addr;
INT send_to_port;
send_to_addr = (dst_addr!=NULL ? dst_addr : m_dst_addr);
send_to_port = (dst_port > 0 ? dst_port : m_dst_port);
#ifdef QT_CORE_LIB
QHostAddress Addr_Dst(send_to_addr);
LOGE("send data: dst addr %s",Addr_Dst.toString().toAscii().data());
res = m_udpSock.writeDatagram((QByteArray)data, (qint64)length, Addr_Dst, m_dst_port);
#elif defined(__linux__)
struct sockaddr_in dest_addr;
dest_addr.sin_family=AF_INET;
if( 0 == strcmp(send_to_addr,"255.255.255.255") ){ //针对广播包的处理
int so_broadcast=1;
//so_broadcast 传递bool值,用于指定SO_BROADCAST是否开启
setsockopt(m_socketId,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));
dest_addr.sin_addr.s_addr=inet_addr(send_to_addr);
LOGE("broad cast!!!!, dst_port[%d]", send_to_port);
}
else
dest_addr.sin_addr.s_addr=inet_addr(send_to_addr);
dest_addr.sin_port=htons(send_to_port);
res = sendto(m_socketId, data, length, MSG_DONTWAIT ,(struct sockaddr*)&dest_addr, sizeof(dest_addr));
#endif
return res;
}
int Udpp::RecvData(BYTE *dst_data, INT max_len){
if(m_rw_mode == UDPP_WRITE_ONLY)
return -1;
INT res=-1;
#ifdef QT_CORE_LIB
res = m_udpSock.readDatagram(dst_data,max_len);
#elif defined(__linux__)
res = recvfrom(m_socketId,dst_data, max_len, MSG_DONTWAIT ,NULL, NULL);
#endif
LOGE("recv data: read port[%d],read len[%d] ", m_local_port, res );
return res;
}
3) main.cpp
int main(){
{
char data[40]="wakawaka";
Udpp udpp("255.255.255.255",6666, 7777,UDPP_READ_WRITE);
for(int i=0; i<<SPAN style="COLOR: #000080">5; i++){
udpp.SendData("555666777",strlen(data),NULL,6666);
LOGE("send data !!!");
fflush(stdout);
for(int i=0; i<<SPAN style="COLOR: #000080">1000000000; i++);
}
for(int i=0; i<<SPAN style="COLOR: #000080">5; i++){
udpp.RecvData(data,sizeof(data));
LOGE("recv data is [%s]",data);
fflush(stdout);
for(int i=0; i<<SPAN style="COLOR: #000080">1000000000; i++);
}
}
while(1);
}
4)
commontypes.h
#ifndef COMMONTYPES_H
#define COMMONTYPES_H
typedef short SHORT;
typedef char BYTE;
typedef unsigned int UINT;
typedef int INT;
#endif // COMMONTYPES_H
5) commonlogs.h
#ifndef COMMONLOGS_H
#define COMMONLOGS_H
#ifdef ANDROID
#include
#define LOGE(format,...) __android_log_print(ANDROID_LOG_ERROR,"hello_hl","file[%s] line[%d] "format"",__FILE__, __LINE__ ,##__VA_ARGS__)
#define LOGI(format,...) __android_log_print(ANDROID_LOG_ERROR,"hello_hl","file[%s] line[%d] "format"",__FILE__, __LINE__ ,##__VA_ARGS__)
#else
#include
#define LOGE(format,...) //{FILE *file_log = fopen("111.log","a+"); \
fprintf(file_log,"file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__); \
fflush(file_log); \
fclose(file_log);}
#define LOGI(format,...) //{FILE *file_log = fopen("111.log","a+"); \
fprintf(file_log,"file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__); \
fflush(file_log); \
fclose(file_log);}
#define LOGD(format,...) //{FILE *file_log = fopen("111.log","a+"); \
fprintf(file_log,"file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__); \
fflush(file_log); \
fclose(file_log);}
#define LOGE(format,...) printf("file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__)
//#define LOGI(format,...) //printf("file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__)
#endif
#endif // COMMONLOGS_H
实验结果:
udp收发均没有问题:
windowQT机器:
linux无qt机器:

加载中…