C语言实现udp客户端,子线程轮询接收数据,QT的界面框架,QMainWindow使用回调函数接收数据,支持windows和linux跨平台。
QMainWindow调用udp
///接收数据回调函数
void udpReceiveMsg(char *data, int32_t nb_data, void *user)
{
MainWindow * mw = (MainWindow*)user;
if(mw == nullptr) return;
mw->UdpRevMsgCallBack(data,nb_data);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
UdpHandle *pUdpHandle = (UdpHandle *)malloc(sizeof(UdpHandle));
pUdpHandle->receive = udpReceiveMsg;
pUdpHandle->user = this;
udp_create(pUdpHandle,(char*)"192.168.72.35",9000,9090);
udp_start(pUdpHandle);
}
MainWindow::~MainWindow()
{
udp_destroy(pUdpHandle);
delete ui;
}
///接收数据处理
void MainWindow::UdpRevMsgCallBack(char *data, int32_t nb_data)
{
QByteArray array(data,nb_data);
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<
udp_sendData(pUdpHandle,ui->textEdit->toPlainText().toLatin1().data(),ui->textEdit->toPlainText().size());
}
UdpClient.h
#ifndef UDPHANDLE_H_ #define UDPHANDLE_H_ #include#include #ifdef _WIN32 #include #include //#define SOCKADDR_IN #define socklen_t int #else #include #include #include #endif typedef struct { int32_t fd; int32_t localPort; int32_t remotePort; int32_t isStart; int32_t isLoop; int32_t notRemoteInit; pthread_t threadId; //char serverIp[30]; void* user; struct sockaddr_in local_addr; struct sockaddr_in remote_addr; void (*receive)(char *data, int32_t nb_data,void* user); void (*startStunTimer)(void* user); }UdpHandle; #ifdef __cplusplus extern "C"{ #endif int32_t udp_create(UdpHandle* udp,char* remoteIp,int32_t remotePort,int32_t plocalPort);//创建udp套接字 void udp_destroy(UdpHandle* udp);//销毁套接字 void udp_start(UdpHandle* udp);//创建线程,启动udp void udp_stop(UdpHandle* udp);//停止线程处理函数 int32_t udp_sendData(UdpHandle* udp,char* p,int32_t plen);//udp发送数据 #ifdef __cplusplus } #endif #endif
UdpClient.c
#include#include #include #include #include "UdpClient.h" #ifndef _WIN32 #define GetSockError() errno #define SetSockError(e) errno = e #define closesocket(s) close(s) #endif int32_t udp_create(UdpHandle *udp, char *remoteIp,int32_t remotePort,int32_t plocalPort) { if (udp == NULL) return -1; udp->localPort = plocalPort; udp->fd = -1; udp->remotePort = remotePort; #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORd(2, 2); WSAStartup(wVersionRequested, &wsaData);//初始化socket库 #endif udp->local_addr.sin_family = AF_INET; udp->local_addr.sin_port = htons(udp->localPort); udp->local_addr.sin_addr.s_addr = INADDR_ANY; udp->fd = socket(AF_INET, SOCK_DGRAM, 0); if(udp->fd < 0) { #ifdef _WIN32 printf("create socket error,udp->fd=%d,WSAGetLastError=%dn",udp->fd,WSAGetLastError());///WSAGetLastError返回当前错误码,windowsAPI #else printf("create socket error,udp->fd=%dn",udp->fd); perror("error:");///linuxAPI,打印输出上一个函数发生的错误,"error:"会首先打印 #endif return -1; } udp->remote_addr.sin_family = AF_INET; udp->remote_addr.sin_port = htons(udp->remotePort); printf("udp->remote_addr.sin_port=%dn",udp->remote_addr.sin_port); udp->notRemoteInit=remotePort>0?0:1; #ifdef _WIN32 udp->remote_addr.sin_addr.S_un.S_addr=inet_addr(remoteIp); #else udp->remote_addr.sin_addr.s_addr = inet_addr(remoteIp); #endif return 0; } void udp_destroy(UdpHandle *udp) { if (udp == NULL) return; udp_stop(udp); if (udp->fd > 0) { closesocket(udp->fd); udp->fd = -1; } } int32_t udp_sendData(UdpHandle *udp, char *data, int32_t nb) { if (udp == NULL || !udp->isStart || udp->notRemoteInit || data==NULL) return -1; return sendto(udp->fd, data, nb, 0, (struct sockaddr*) &udp->remote_addr,sizeof(struct sockaddr)) > 0 ? 0 : 1; } void* run_udp_thread(void *obj) { UdpHandle *udp = (UdpHandle*) obj; udp->isStart = 1; #ifdef _WIN32 int32_t timeout=200; setsockopt(udp->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(timeout)); #else struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 200000; // 200 ms setsockopt(udp->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &tv, sizeof(struct timeval)); #endif printf("udp server is starting,localPort=%dn", udp->localPort); if (bind(udp->fd, (struct sockaddr*) &udp->local_addr,sizeof(struct sockaddr_in)) < 0) { printf("Udp server bind errorn"); #ifdef _WIN32 printf("WSAGetLastError=%dn",WSAGetLastError()); #else perror("error:"); #endif return NULL; } char buffer[2048] = { 0 }; udp->isLoop = 1; int32_t len = 0; // if (!udp->notRemoteInit&&udp->startStunTimer) udp->startStunTimer(udp->user); socklen_t src_len = sizeof(struct sockaddr_in); while (udp->isLoop) { struct sockaddr_in src; memset(&src, 0, src_len); memset(buffer, 0, 2048); if ((len = recvfrom(udp->fd, buffer, 2048, 0, (struct sockaddr*) &src, &src_len)) > 0) { if(udp->notRemoteInit) { udp->remotePort = ntohs(src.sin_port); udp->remote_addr.sin_port = src.sin_port;//htons(udp->remotePort); #ifdef _WIN32 udp->remote_addr.sin_addr.S_un.S_addr=src.sin_addr.S_un.S_addr; #else udp->remote_addr.sin_addr.s_addr = src.sin_addr.s_addr; #endif udp->notRemoteInit=0; //if (udp->startStunTimer) udp->startStunTimer(udp->user); } if (udp->receive) udp->receive(buffer, len, udp->user); } } udp->isStart = 0; closesocket(udp->fd); udp->fd = -1; return NULL; } void udp_start(UdpHandle *udp) { if (udp == NULL) return; if (pthread_create(&udp->threadId, 0, run_udp_thread, udp)) { printf("start could not start threadn"); } } void udp_stop(UdpHandle *udp) { if (udp == NULL) return; udp->isLoop = 0; while (udp->isStart) usleep(1000); }



