zoukankan      html  css  js  c++  java
  • 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 }  
  • 相关阅读:
    C语言 · 最大最小值
    C语言 · 三个整数的排序
    C语言 · 简单加法
    C语言 · FJ的字符串
    C语言 · 分解质因数
    C语言 · 数的统计
    C语言 · 成绩的等级输出
    C语言 · 区间K大数查询
    shell学习目录
    数据库学习目录
  • 原文地址:https://www.cnblogs.com/91program/p/5208729.html
Copyright © 2011-2022 走看看