Cách triển khai UDP Client trong MFC cho Windows CE

Khi đã thiết lập kết nối RAS và giao thức TCP/IP hoàn tất, bước tiếp theo là truyền dữ liệu thông qua UDP. Dưới đây là ví dụ triển khai UDP client với hai phần: file header và file source.

File header NetUDPClient.h:

 1 // NetUDPClient.h: interface for the CNetUDP class.
 2 //
 3 //////////////////////////////////////////////////////////////////////
 4 #ifndef _NET_UDP_CLIENT_H_
 5 #define _NET_UDP_CLIENT_H_
 6 #if _MSC_VER > 1000
 7 #pragma once
 8 #endif // _MSC_VER > 1000
 9 #include "WinSock.h"
10 #pragma pack(push,1)
11 
12 // Ham callback khi co loi xay ra
13 typedef void (CALLBACK *ONUDPERROR)(CWnd *,int);
14 // Ham callback khi nhan duoc du lieu
15 typedef void (CALLBACK *ONUDPRECV)(CWnd *,char *buf,int bufLen,sockaddr *);
16 
17 class CNetUDP
18 {
19 public:
20     CNetUDP();
21     virtual ~CNetUDP();
22 public:
23     DWORD Open(CWnd *pWnd, int nLocalPort, LPCTSTR szRemoteHost, int nRemotePort);
24     DWORD Close(void);
25     bool SendData(const char *pBuffer, int nLength);
26     BOOL IsConnected(void);
27 
28     // Su kien loi UDP
29     ONUDPERROR m_pfnOnError;
30     // Su kien nhan du lieu UDP
31     ONUDPRECV  m_pfnOnReceive;
32 
33 private:
34     SOCKET m_hUDPSocket;
35     struct sockaddr_in m_stRemoteAddress;
36     HANDLE m_hExitEvent;
37     CWnd *m_pParentWnd;
38     BOOL m_bConnected;
39     static UINT DataReceiveThread(LPVOID lpParam);
40 };
41 #pragma pack(pop)
42 #endif

File source NetUDPClient.cpp:

 1 // NetUDPClient.cpp: implementation of the CNetUDP class.
 2 //
 3 //////////////////////////////////////////////////////////////////////
 4 #include "stdafx.h"
 5 #include "NetUDPClient.h"
 6 
 7 #ifdef _DEBUG
 8 #undef THIS_FILE
 9 static char THIS_FILE[]=__FILE__;
 10 #define new DEBUG_NEW
11 #endif
12 
13 #define UDP_PACKET_SIZE 2048
14 
15 //////////////////////////////////////////////////////////////////////
16 // Construction/Destruction
17 //////////////////////////////////////////////////////////////////////
18 
19 CNetUDP::CNetUDP()
20 {
21     m_bConnected = FALSE;
22 }
23 
24 CNetUDP::~CNetUDP()
25 {
26 }
27 
28 /*
29  * Mo cong UDP
30  * Tra ve: 1 = thanh cong; gia tri am = that bai
31 */
32 DWORD CNetUDP::Open(CWnd* pWnd,
33                     int nLocalPort,
34                     LPCTSTR szRemoteHost,
35                     int nRemotePort)
36 {
37     WSADATA wsaData;
38 
39     m_pParentWnd = pWnd;
40     if(WSAStartup(MAKEWORD(1,1),&wsaData) != 0)
41     {
42         return -1;
43     }
44
45     // Tao socket UDP
46     m_hUDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
47     if(m_hUDPSocket == INVALID_SOCKET)
48     {
49         return -2;
50     }
51
52     SOCKADDR_IN stLocalAddress;
53     stLocalAddress.sin_family = AF_INET;
54     stLocalAddress.sin_port = htons(nLocalPort);
55     stLocalAddress.sin_addr.s_addr = INADDR_ANY;
56
57     // Bind dia chi
58     if(bind(m_hUDPSocket, (sockaddr*)&stLocalAddress, sizeof(stLocalAddress)) != 0)
59     {
60         return -3;
61     }
62
63     // Cai dat che do khong dong bo
64     DWORD dwNonBlocking = 1;
65     ioctlsocket(m_hUDPSocket, FIONBIO, &dwNonBlocking);
66
67     // Tao su kien thoat thread
68     m_hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
69
70     // Khoi dong thread nhan du lieu
71     AfxBeginThread(DataReceiveThread, this);
72
73     m_stRemoteAddress.sin_family = AF_INET;
74     m_stRemoteAddress.sin_port = htons(nRemotePort);
75
76     // Chuyen doi wide char sang ANSI
77     char szRemoteIP[256];
78     memset(szRemoteIP, 0, 256);
79     WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
80                         szRemoteHost, wcslen(szRemoteHost),
81                         szRemoteIP, wcslen(sRemoteHost), NULL, NULL);
82     m_stRemoteAddress.sin_addr.s_addr = inet_addr(szRemoteIP);
83
84     m_bConnected = TRUE;
85     return 1;
86 }
87 
88 /*
89  * Dong cong UDP
90  * Tra ve: 1 = thanh cong; gia tri am = that bai
91 */
92 DWORD CNetUDP::Close(void)
93 {
94     m_bConnected = FALSE;
95
96     // Thong bao cho thread thoat
97     SetEvent(m_hExitEvent);
98     Sleep(1000);
99     CloseHandle(m_hExitEvent);
100
101     if(closesocket(m_hUDPSocket) == SOCKET_ERROR)
102     {
103         return -1;
104     }
105
106     // Giai phong tai nguyen Winsock
107     if(WSACleanup() == SOCKET_ERROR)
108     {
109         return -2;
110     }
111     return 1;
112 }
113 
114 /*
115  * Gui du lieu qua UDP
116  * Tra ve: so byte da gui, -1 neu that bai
117 */
118 bool CNetUDP::SendData(const char *pBuffer, int nLength)
119 {
120     int nSentBytes = 0;
121     int nError = 0;
122
123     nSentBytes = sendto(m_hUDPSocket, pBuffer, nLength, 0,
124                         (sockaddr*)&m_stRemoteAddress, sizeof(m_stRemoteAddress));
125
126     if(nSentBytes == SOCKET_ERROR)
127     {
128         nError = WSAGetLastError();
129         if(m_pfnOnError != NULL)
130             m_pfnOnError(m_pParentWnd, nError);
131         return false;
132     }
133     return true;
134 }
135 
136 /*
137  * Thread nhan du lieu
138  */
139 UINT CNetUDP::DataReceiveThread(LPVOID lpParam)
140 {
141     CNetUDP *pUDP = (CNetUDP *)lpParam;
142     fd_set fdsReadSet;
143     int nSelectResult = 0;
144     TIMEVAL tvTimeout;
145     char *pszRecvBuffer = NULL;
146     SOCKADDR_IN stSenderAddr;
147     int nAddrLen = 0;
148     int nBytesReceived = 0;
149     int nLastError = 0;
150
151     tvTimeout.tv_sec = 1;
152     tvTimeout.tv_usec = 0;
153
154     while(TRUE)
155     {
156         // Kiem tra su kien thoat
157         if(WaitForSingleObject(pUDP->m_hExitEvent, 0) == WAIT_OBJECT_0)
158         {
159             break;
160         }
161
162         // Khoi tao tap file descriptor
163         FD_ZERO(&fdsReadSet);
164
165         // Them socket vao tap
166         FD_SET(pUDP->m_hUDPSocket, &fdsReadSet);
167
168         // Kiem tra trang thai I/O
169         nSelectResult = select(0, &fdsReadSet, NULL, NULL, &tvTimeout);
170
171         if(nSelectResult == SOCKET_ERROR)
172         {
173             nLastError = WSAGetLastError();
174             if(pUDP->m_pfnOnError != NULL)
175                 pUDP->m_pfnOnError(pUDP->m_pParentWnd, nLastError);
176             break;
177         }
178
179         if(nSelectResult > 0)
180         {
181             if(FD_ISSET(pUDP->m_hUDPSocket, &fdsReadSet))
182             {
183                 stSenderAddr.sin_family = AF_INET;
184                 stSenderAddr.sin_port = htons(pUDP->m_stRemoteAddress.sin_port);
185                 stSenderAddr.sin_addr.s_addr = INADDR_ANY;
186                 nAddrLen = sizeof(stSenderAddr);
187
188                 pszRecvBuffer = new char[UDP_PACKET_SIZE];
189                 memset(pszRecvBuffer, 0, UDP_PACKET_SIZE);
190
191                 nBytesReceived = recvfrom(pUDP->m_hUDPSocket, pszRecvBuffer,
192                                           UDP_PACKET_SIZE, 0,
193                                           (SOCKADDR *)&stSenderAddr, &nAddrLen);
194
195                 if(nBytesReceived == SOCKET_ERROR)
196                 {
197                     nLastError = WSAGetLastError();
198                     if(pUDP->m_pfnOnError != NULL)
199                         pUDP->m_pfnOnError(pUDP->m_pParentWnd, nLastError);
200                     delete [] pszRecvBuffer;
201                     break;
202                 }
203                 else if(nBytesReceived == 0)
204                 {
205                     nLastError = WSAGetLastError();
206                     if(pUDP->m_pfnOnError != NULL)
207                         pUDP->m_pfnOnError(pUDP->m_pParentWnd, nLastError);
208                     delete [] pszRecvBuffer;
209                     break;
210                 }
211                 else
212                 {
213                     // Xu ly du lieu nhan duoc
214                     if(pUDP->m_pfnOnReceive != NULL)
215                         pUDP->m_pfnOnReceive(pUDP->m_pParentWnd,
216                                              pszRecvBuffer, nBytesReceived,
217                                              (SOCKADDR *)&stSenderAddr);
218
219                     delete [] pszRecvBuffer;
220                     pszRecvBuffer = NULL;
221                 }
222             }
223         }
224     }
225     return 0;
226 }
227 
228 /*
229  * Kiem tra trang thai socket
230  */
231 BOOL CNetUDP::IsConnected(void)
232 {
233     return m_bConnected;
234 }

Vi du su dung:

Định nghĩa callback:

1 CNetUDP m_udpClient;
2 static void CALLBACK OnUDPReceive(CWnd *pWnd, char *buf, int nLen, sockaddr *addr);
3 static void CALLBACK OnUDPFailure(CWnd *pWnd, int nError);
 1 // Tao ket noi UDP
 2 m_udpClient.m_pfnOnReceive = OnUDPReceive;
 3 m_udpClient.m_pfnOnError = OnUDPFailure;
 4 DWORD dwResult = m_udpClient.Open(this, m_nLocalPort, m_strRemoteIP, m_nRemotePort);
 5 
 6 if(dwResult <= 0)
 7 {
 8     RETAILMSG(1, (L"UDP Client - Open failed\r\n"));
 9     return;
10 }
11 else
12 {
13     RETAILMSG(1, (L"UDP Client - Open success\r\n"));
14 }
15 
16 // Dong ket noi UDP
17 if(m_udpClient.Close() == 1)
18 {
19     RETAILMSG(1, (L"UDP Client - Close success\r\n"));
20 }
21 else
22 {
23     RETAILMSG(1, (L"UDP Client - Close failed\r\n"));
24 }

Đăng vào ngày 27 tháng 5 lúc 22:52