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 }