UDP 通讯代码

在使用 RAS使用拨号网络拨号的类建立 TCP/IP后,接下来是通过 TCP/UDP 进行数据的传输。

下面是使用 UDP 的例子,分为头文件和源代码

头文件zhUDPCE.h :

 1 // UDP.h: interface for the CZhUDP class.
 2 //
 3 //////////////////////////////////////////////////////////////////////
 4 #ifndef _ZH_DUP_CE_H_
 5 #define _ZH_DUP_CE_H_
 6 #if _MSC_VER > 1000
 7 #pragma once
 8 #endif // _MSC_VER > 1000
 9 #include "WinSock.h"
10 #pragma pack(push,1)
11 //UDP客户端发送错误回调函数
12 typedef void (CALLBACK *ONZhUDPERROR)(CWnd *,int);
13 //UDP客户端接收数据回调函数
14 typedef void (CALLBACK *ONZhUDPRECV)(CWnd *,char *buf,int bufLen,sockaddr *);
15 class CZhUDP
16 {
17 public:
18     CZhUDP();
19     virtual ~CZhUDP();
20 public:
21     DWORD Open(CWnd *pWnd,int localPort, LPCTSTR remoteHost ,int remotePort);
22     DWORD Close(void);
23     bool SendData(const char *pBuf,int len);
24     BOOL IsSocketOpen(void);
25     // UDP 错误事件
26     ONZhUDPERROR m_OnUdpError;
27     // UDP 数据接收事件
28     ONZhUDPRECV  m_OnUdpRecv;
29 private:
30     SOCKET m_UDPSocket;
31     struct sockaddr_in m_RemoteAddr;      // 存储远程通讯地址
32     HANDLE m_ExitThreadEvent;             // 线程退出事件
33     CWnd *m_pOwnerWnd;                    // 存储父窗体句柄
34     BOOL m_bIsOpen;
35     static UINT RecvThread(LPVOID lparam);
36 };
37 #pragma pack(pop)
38 #endif  

源文件zhUDPCE.cpp :

  1 // UDP.cpp: implementation of the CZhUDP class.
  2 //
  3 //////////////////////////////////////////////////////////////////////
  4 #include "stdafx.h"
  5 #include "zhUDPCE.h"
  6 #ifdef _DEBUG
  7 #undef THIS_FILE
  8 static char THIS_FILE[]=__FILE__;
  9 #define new DEBUG_NEW
 10 #endif
 11 #define ZHUDP_BUFFER_SIZE 1024
 12 //////////////////////////////////////////////////////////////////////
 13 // Construction/Destruction
 14 //////////////////////////////////////////////////////////////////////
 15 CZhUDP::CZhUDP()
 16 {
 17     m_bIsOpen = FALSE;
 18 }
 19 CZhUDP::~CZhUDP()
 20 {
 21 }
 22 /*
 23  * 功能:打开UDP通讯端口
 24  * 返回值:1代表成功;-1,-2,-3等都代表失败
 25 */
 26 DWORD CZhUDP::Open(CWnd* pWnd,          // 父窗体指针
 27                    int localPort,       // 远程UDP端口
 28                    LPCTSTR remoteHost,  // 远程IP地址
 29                    int remotePort)      // 远程UDP端口
 30 {
 31     WSADATA wsa;
 32
 33     m_pOwnerWnd = pWnd;
 34     if(WSAStartup(MAKEWORD(1,1),&wsa) != 0)
 35     {
 36         return -1;
 37     }
 38
 39     // 创建UDP套接字
 40     m_UDPSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
 41     if(INVALID_SOCKET == m_UDPSocket)
 42     {
 43         return -2;
 44     }
 45
 46     SOCKADDR_IN localAddr;
 47     localAddr.sin_family = AF_INET;
 48     localAddr.sin_port = htons(localPort);
 49     localAddr.sin_addr.s_addr=INADDR_ANY;
 50
 51     // 绑定地址
 52     if(bind(m_UDPSocket,(sockaddr*)&localAddr,sizeof(localAddr)) != 0)
 53     {
 54         return -3;
 55     }
 56
 57     // 设置非堵塞通讯
 58     DWORD wCmdParam = 1;
 59     ioctlsocket(m_UDPSocket,FIONBIO,&wCmdParam);
 60     // 创建一个线程退出事件
 61     m_ExitThreadEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
 62
 63     // 创建通讯线程
 64     AfxBeginThread(RecvThread,this);
 65
 66     m_RemoteAddr.sin_family = AF_INET;
 67     m_RemoteAddr.sin_port = htons(remotePort);
 68     // 此处要将双字节转换成单字节
 69     char ansiRemoteHost[255];
 70     ZeroMemory(ansiRemoteHost,255);
 71     WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,remoteHost,wcslen(remoteHost),ansiRemoteHost,wcslen(remoteHost),NULL,NULL);
 72     m_RemoteAddr.sin_addr.s_addr=inet_addr(ansiRemoteHost);
 73     m_bIsOpen = TRUE;
 74     return 1;
 75 }
 76 /*
 77  * 功能:关闭UDP通讯端口
 78  * 返回值:1代表成功;-1,-2等都代表失败
 79 */
 80 DWORD CZhUDP::Close(void)
 81 {
 82     m_bIsOpen = FALSE;
 83     // 设置通讯线程退出事件,通知线程退出
 84     SetEvent(m_ExitThreadEvent);
 85     Sleep(1000);
 86     CloseHandle(m_ExitThreadEvent);
 87     if(closesocket(m_UDPSocket) == SOCKET_ERROR)
 88     {
 89         return -1;
 90     }
 91
 92     // 释放socket资源
 93     if(WSACleanup() == SOCKET_ERROR)
 94     {
 95         return -2;
 96     }
 97     return 1;
 98 }
 99 /*
100 * 功能:发送数据
101 * 返回值:发送成功代表实际发送的字节数,否则返回-1
102 */
103 bool CZhUDP::SendData(const char *pBuf, // 缓冲区数据
104                       int len)          // 缓冲数据长度
105 {
106     int nBytes = 0;
107     int nErrorCode = 0;
108     nBytes = sendto(m_UDPSocket,pBuf,len,0,(sockaddr*)&m_RemoteAddr,sizeof(m_RemoteAddr));
109     if(SOCKET_ERROR == nBytes)
110     {
111         nErrorCode = WSAGetLastError();
112         m_OnUdpError(m_pOwnerWnd,nErrorCode);
113         return false;
114     }
115     return true;
116 }
117 /*
118  * 功能:接收线程函数
119  * 返回值:无意义。
120 */
121 UINT CZhUDP::RecvThread(LPVOID lparam)  // 指传进线程的参数
122 {
123     CZhUDP *pSocket;
124     pSocket = (CZhUDP *)lparam;
125     fd_set fdRead;
126     int ret = 0;
127     TIMEVAL tvTimeout;
128     char *pcRecvBuf = NULL;
129     SOCKADDR_IN tmpAddr;
130     int tmpRecvLen = 0;
131     int recvLen = 0;
132     int iErrorCode = 0;
133     char *pcRecvedBuf = NULL;
134     int recvedBufLen = 0;
135     tvTimeout.tv_sec = 1;
136     tvTimeout.tv_usec = 0;
137     while(TRUE)
138     {
139         // 收到退出事件,结束线程
140         if(WaitForSingleObject(pSocket->m_ExitThreadEvent,0) == WAIT_OBJECT_0)
141         {
142             break;
143         }
144         // 初始化 set
145         FD_ZERO(&fdRead);
146
147         // 将 pSocket->m_UDPSocket 套接字添加到集合中
148         FD_SET(pSocket->m_UDPSocket,&fdRead);
149
150         // 判断套接字I/O状态
151         ret = select(0,&fdRead,NULL,NULL,&tvTimeout);
152
153         if(SOCKET_ERROR == ret)
154         {
155             iErrorCode = WSAGetLastError();
156             pSocket->m_OnUdpError(pSocket->m_pOwnerWnd,iErrorCode);
157             break;
158         }
159
160         if(ret > 0)
161         {
162             if(FD_ISSET(pSocket->m_UDPSocket,&fdRead))
163             {
164                 tmpAddr.sin_family = AF_INET;
165                 tmpAddr.sin_port = htons(pSocket->m_RemoteAddr.sin_port);
166                 tmpAddr.sin_addr.s_addr = INADDR_ANY;
167                 tmpRecvLen = sizeof(tmpAddr);
168
169                 pcRecvBuf = new char[ZHUDP_BUFFER_SIZE];
170                 pcRecvedBuf = new char[ZHUDP_BUFFER_SIZE];
171                 ZeroMemory(pcRecvBuf,ZHUDP_BUFFER_SIZE);
172                 ZeroMemory(pcRecvedBuf,ZHUDP_BUFFER_SIZE);
173                 recvLen = recvfrom(pSocket->m_UDPSocket,pcRecvBuf,ZHUDP_BUFFER_SIZE,0,(SOCKADDR *)&tmpAddr,&tmpRecvLen);
174                 if(SOCKET_ERROR == recvLen)
175                 {
176                     iErrorCode = WSAGetLastError();
177                     pSocket->m_OnUdpError(pSocket->m_pOwnerWnd,iErrorCode);
178
179                     break;
180                 }
181                 else if(0 == recvLen)
182                 {
183                     iErrorCode = WSAGetLastError();
184                     pSocket->m_OnUdpError(pSocket->m_pOwnerWnd,iErrorCode);
185
186                     break;
187                 }
188
189                 else
190                 {
191                     // 此处添加解析程序,将接收到的数据解析后
192                     pSocket->m_OnUdpRecv(pSocket->m_pOwnerWnd,pcRecvBuf,recvedBufLen,(SOCKADDR *)&tmpAddr);
193
194                     delete []pcRecvBuf;
195                     delete []pcRecvedBuf;
196                     pcRecvBuf = NULL;
197                     pcRecvedBuf = NULL;
198                 }
199
200             }
201         }
202     }
203     return 0;
204 }
205 /*
206  * 功能:判断 Socket 状态
207 */
208 BOOL CZhUDP::IsSocketOpen(void)
209 {
210     return m_bIsOpen;
211 }  

使用示例:

定义

1 CZhUDP m_ZhUdpCE;
2 static void CALLBACK OnZhUdpRecv(CWnd *pWnd,char *buf,int nLen,sockaddr *addr);
3 static void CALLBACK OnZhUdpError(CWnd *pWnd,int nError);
 1 // 建立 UDP 链接
 2 m_ZhUdpCE.m_OnUdpRecv = OnZhUdpRecv;
 3 m_ZhUdpCE.m_OnUdpError = OnZhUdpError;
 4 DWORD nResult = m_ZhUdpCE.Open(this,m_iLocalPort,m_csRemoteHost,m_iRemotePort);
 5 if (nResult <= 0)
 6 {
 7     RETAILMSG(1,(L"DUPClient,Open UDP failed/r/n"));
 8     return;
 9 }
10 else
11 {
12     RETAILMSG(1,(L"DUPClient,Open UDP success/r/n"));
13 }
14 // 断开 UDP 链接
15 if(1 == m_ZhUdpCE.Close())
16 {
17     RETAILMSG(1,(L"DUPClient,Close UDP success/r/n"));
18 }
19 else
20 {
21     RETAILMSG(1,(L"DUPClient,Close UDP failed/r/n"));
22 }  
时间: 2024-08-09 06:35:10

UDP 通讯代码的相关文章

UDP通讯代码

UDP客户端代码: import socket # 创建套接字 socket.AF_INET:IPV4 socket.SOCK_DGRAM:UDP协议 udp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) data=input("请输入:") # 发送数据 udp_client.sendto(data.encode("utf-8"),("192.168.43.72",8080)) #

C#中的TCP通讯与UDP通讯

最近做了一个项目,主要是给Unity3D和实时数据库做通讯接口.虽然方案一直在变:从开始的UDP通讯变为TCP通讯,然后再变化为UDP通讯;然后通讯的对象又发生改变,由与数据库的驱动进行通讯(主动推送数据给驱动,数据库中数据发生变化把数据以UDP报文形式发送客户端)改为与实时数据库进行直接通讯(自己发送报文修改数据库中的数据,自己请求需要获取的数据并接收自己请求的数据):现在这个项目基本完结,由于这个过程既接触到了UDP又接触到了TCP,现在对其进行一番总结. 阅读目录 TCP通讯协议与UDP通

LWIP裸机环境下实现TCP与UDP通讯

前面移植了LWIP,并且简单的实用了DHCP的功能,今天来使用一下实际的数据通讯的功能 首先是实现TCP客户端,我先上代码 #ifndef __TCP_CLIENT_H_ #define __TCP_CLIENT_H_ #include "network.h" //连接状态 enum tcp_client_states { ES_NONE = 0, ES_RECEIVED, //接收到了数据 ES_CLOSING //连接关闭 }; //TCP服务器状态 struct tcp_clie

UDP通讯

UDP通讯方式非常简单,但数据安全性低.丢包率高. UDP通讯过程: 发送时,指定接收方IP和端口,即可发送数据 接收时,一直监听端口的信息,有信息来即可接收到. UDP编程: 1.编写界面 2.添加数据报组件 3.UDP程序编写 事件 主窗口.创建完毕() 结束 事件 变量 监听状态 为 逻辑型 变量 监听端口 为 整数型 事件 按钮1.被单击() 如果 监听状态 = 假 则 监听端口 = 编辑框1.内容 数据报1.开始监听(监听端口) 监听状态 = 真 弹出提示("UDP开始监听!"

TCP和UDP Client 代码

最近学习要求做网络编程,使用从网上找了一些资料,主要是网络协议的分层等通讯,你可以查看英文版的资料:CScharp网络编程英文版 下面直接给出代码吧,我想一看应该就懂. TCP Client 代码: using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; namespace TcpLib { p

[学习笔记]Java网络编程之UDP通讯

1. 体系结构 计算机网络各层及其协议的集合,称为网络的体系结构.目前公认的计算机网络体系结构有概念清楚理论完善的OSI七层协议结构和实际上广泛应用的TCP/IP四层体系结构. 2. 各层概述 应用层:直接为用户的程序提供服务,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等. 运输层:负责向两个主机中进程之间的通信提供服务,主要使用面向连接的TCP协议和无连接的UDP协议. 网络层:负责为分组交换网上不同主机提供地址交付的通信服务,该层使用IP协议,所以在该层传送的数据称之为IP数

Java简单的UDP通讯例子

内容:简单的UDP通讯例子. Receiver: public class Receiver { public static void main(String[] args) { DatagramSocket ds = null; try { //UDP接收端 ds = new DatagramSocket(8080); //定义将UDP的数据包接收到什么地方 byte[] buf = new byte[1024]; //定义UDP的数据接收包 DatagramPacket dp = new D

QUdpSocket-Qt使用Udp通讯实现服务端和客户端

版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QUdpSocket-Qt使用Udp通讯实现服务端和客户端     本文地址:http://techieliang.com/2017/12/532/ 文章目录 1. QNetworkDatagram 2. 客户端 3. 服务端 4. 消息收发 1. QNetworkDatagram qt网络报文,可用其建立一个通讯内容包括目标ip.端口号.数据内容.同时接收到的信息也未此类型,可以访问接收数

W5100——TCP/UDP通讯

前段时间接触到W5100这款集成了PHY的以太网芯片,用作工业场合的通讯以及数据传输功能,现在回顾一下当时调试代码的经过. 大概框架:  stm32F4通过8位FSMC总线和W5100通讯. 用这款芯片的理由:集成了PHY,避免了外部再接转换芯片,另外有4个独立的SOCKET,可并行工作. TCP: 服务器端: 配置FSMC端口--->IP和端口绑定(打开了并行总线和自加位,写入gateway和IP)--->Socket初始化--->监听Socket--->任务子函数 客户端: 配