1. UDP là gì?
- Thật ra mình đã giới thiệu về UDP ở phần tạo SOCKET rồi nhưng mình nói lại 1 xíu cho nhanh. UDP là một trong 2 giao thức chính của mô hình TCP/IP
để truyền tải dữ liệu. CLIENT - SERVER sử dụng UDP sẽ không bao giờ quan tâm đến về đề dữ liệu có chính xác hay không? Bên gửi cứ gửi và bên nhận cứ
nhận, nhận không được thì mặc kệ...
- Người ta sử dụng UDP trong những ứng dụng cần truyền dữ liệu nhanh như
CHAT, GAME ONLINE, ....
- Và lần này mình sẽ DEMO 1 bộ ứng dụng Client - Server liên lạc với nhau
mà Client không cần biết IP Server sử dụng cơ chế Multicast hay Broadcast
2. BROADCAST hay MULTICAST là gì? a. Broadcast
Chúng ta biết IP chia thành 3 lớp là A,B,C.
Trong cấu trúc địa chỉ IP bao gồm NET_ID và HOST_ID
-> Các host chỉ thấy nhau (liên lạc được) khi chúng có cùng NET_ID.
-> Muốn host liên lạc khi khác NET_ID thì cần phải có cơ chế định tuyến (sử
dụng thiết bị router, Server có cấu hình Routing ...)
=> Như vậy trong 1 NET_ID phải có 1 địa chỉ nào đó để đại diện cho tất cả các HOST đường mạng đó và đó chính là địa chỉ Broadcast
Ví dụ:
Lớp A:
-> Tất cả đều có chung 1 đường mạng 10.0.0.0
-> Và IP đại điện là IP Broadcast: 10.255.255.255.
Nghĩa là khi có 1 gói tin UDP gởi tới địa chỉ này thì tất cả các host trên đều
nhận được
b. Multicast
- Địa chỉ Broadcast đại diện cho tất cả các Host nhưng trên cùng 1 đường
mạng.
- Địa chỉ Multicast đại diện cho tất cả các HOST trên tất cả các đường mạng
khác nhau
Hay chính xác hơn thì địa chỉ "255.255.255.255" chính là địa chỉ Multicast.
Khi gởi 1 gói tin UDP Packet tới địa chỉ này thì tất cả các host có thể liên lạc được với host gửi (khác đường mạng phải có cơ chế định tuyến) đèu nhận được
gói tin này.
Tuy nhiên lưu ý 1 điều là Multicast hay Broadcast chỉ có giá trị trong IPLAN 2. Chương trình DEMO
Ý tưởng: Bạn đã chơi Game Haftlife chưa???
- Rõ ràng máy Server trong mạng LAN có thể là bất cứ máy tính nào mà Gamer chọn Create Game?
=> Vậy làm sao Client có thể biết được IP máy chủ để Connect.
Và nó phải sử dụng cơ chế tìm IP SERVER sử dụng UDP Broadcast. Và chương trình DEMO của mình sẽ như sau:
a. SERVER
Cũng như TCP. Nhiệm vụ chính của nó là lắng nghe, tuy nhiên chỉ khác chức năng là không cần phải chấp nhận kết nối từ Client.
// Thiết lập IP PORT pAddr->sin_family = AF_INET; pAddr->sin_port = htons(MY_PORT); pAddr->sin_addr.S_un.S_addr = ADDR_ANY;
// Tìm địa chỉ IP của SERVER <sau này trả lại cho CLIENT>
char lpName[100]; char lpMyIP[100]={0};
hostent* pMyServer = gethostbyname(lpName);
u_long myIP = *(u_long*)pMyServer->h_addr_list[0]; strcpy(lpMyIP,inet_ntoa(*(in_addr*)&myIP));
// --- // Đưa thông tin IP và PORT cho SOCKET
nResult = bind(*sock,(sockaddr*)pAddr,sizeof(sockaddr)); if (nResult == -1){
cout << "Loi thiet lap IP va PORT\n"; HuyWinsock(sock);
return 1; }
cout << "Dang lang nghe ket noi tren IP: " << lpMyIP << " port: " << MY_PORT << "\n\n"; int nAddrLen; int nRevc; int nSend; sockaddr_in IPClient; char buff[512]={0}; while (1){ // Nhận kết nối từ CLIENT nAddrLen = sizeof(sockaddr_in); nRevc = recvfrom(*sock,buff,sizeof(buff),0, (sockaddr*)&IPClient,&nAddrLen); buff[nRevc-1] = 0;
cout << "Nhan ket toi tu CLIENT IP: " << inet_ntoa(IPClient.sin_addr) << "\n";
cout << "Noi dung: \"" << buff << "\"\n"; // Kiểm tra yêu cầu của CLIENT
if (strcmpi("IP may chu dau???",buff)==0){ cout << "Hieu yeu cau tu Client!\n"; // Gửi trả lại cho CLIENT địa chỉ IP của mình
nSend =
sendto(*sock,lpMyIP,strlen(lpMyIP),0,(sockaddr*)&IPClient,sizeof(IPClient)) ;
cout << "Gui lai client: " << nSend << " Bytes\n"; }
else{
cout << "Khong hieu yeu cau tu Client!\n"; }
cout << "\n"; }
b. CLIENT
-> Nhiệm vụ chính của CLIENT là gửi 1 gói tin BROADCAST với PORT quy định sẵn
Trong chương trình của CLIENT có 1 hàm rất quan trọng để cho phép
SOCKET gởi tới địa chỉ BROADCAST
setsockopt(*sock,SOL_SOCKET,SO_BROADCAST,(char*)&b SockBroadcast,sizeof(BOOL));
- Op tùy chọn ở đây là : SO_BROADCAST (gởi gói tin Broadcast);
- bSockBroadcast: TRUE (cho phép), FALSE (không cho phép). Hàm này có rất nhiều Option. Các bạn có thể tham khảo thêm MSDN. int FindServer(SOCKET* sock,sockaddr_in* pServerAddr){ BOOL bSockBroadcast=true; setsockopt(*sock,SOL_SOCKET,SO_BROADCAST,(char*)&bSockBroadcas t,sizeof(BOOL)); pServerAddr->sin_family = AF_INET; pServerAddr->sin_port = htons(MY_PORT);
pServerAddr->sin_addr.S_un.S_addr = inet_addr("255.255.255.255"); // Địa
chỉ đích là MULTICAST
int nRevc;
int nAddrLen;
char buff[512]="IP may chu dau???"; // Thông tin gửi tới máy chủ
// Gửi tới máy chủ nSend =
sendto(*sock,buff,sizeof(buff),0,(sockaddr*)pServerAddr,sizeof(sockaddr_in)) ;
cout << "Da gui " << nSend << " bytes\n";
// Nhận hồi âm của máy chủ
sockaddr_in ServerIP;
nAddrLen = sizeof(sockaddr_in);
nRevc = recvfrom(*sock,buff,sizeof(buff),0, (sockaddr*)&ServerIP, &nAddrLen);
buff[nRevc] = 0;
cout << "Da nhan " << nRevc << " bytes\n";
cout << "Noi dung nhan <IP SERVER>: " << buff << "\n"; return 0;
}
c. Download Demo here Còn tiếp ...