[VC++] Lập Trình Mạng Với Thư Viện Winsock
lượt xem 62
download
I. KHỞI ĐỘNG WINSOCK Để lập trình được Winsock chúng ta sẽ khai báo thư viện winsock2.h (chứa các prototypes) và 1 file lib (chính là file .cpp đã được biên dịch thành .lib) có tên là ws2_2.lib. Bây giờ hãy tạo 1 project Windows32 Console Project. Lưu ý: Chúng ta không khai báo trong file .cpp có hàm main mà khai báo trong file stdafx.h. Đây là cách khai báo thư viện của Visual C++. #include ... #include #pragma comment (lib,"ws2_32.lib") Và bây giờ sẽ là những hàm để khởi tạo Winsock: int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);...
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: [VC++] Lập Trình Mạng Với Thư Viện Winsock
- [VC++] Lập Trình Mạng Với Thư Viện Winsock
- [VC++] Lập Trình Mạng Với Thư Viện Winsock I. KHỞI ĐỘNG WINSOCK Để lập trình được Winsock chúng ta sẽ khai báo th ư viện winsock2.h (chứa các prototypes) và 1 file lib (chính là file .cpp đã được biên dịch thành .lib) có tên là ws2_2.lib. Bây giờ hãy tạo 1 project Windows32 Console Project. Lưu ý: Chúng ta không khai báo trong file .cpp có hàm main mà khai báo trong file stdafx.h. Đây là cách khai báo thư viện của Visual C++. #include ... #include #pragma comment (lib,"ws2_32.lib") Và bây giờ sẽ là những hàm để khởi tạo Winsock: int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); Trong đó: - wVersionRequested là phiên bản thư viện mà mình sử dụng. Ở đây sẽ là giá trị 0x0202 có nghĩa là phiên bản 2.2. Chúng ta có thể dùng macro MAKEWORD(2,2) để trả về giá trị 0x0202. - lpWSData là m ột số thông tin bổ sung sẽ đ ược trả về sau khi gọi khởi tạo Winsock.: typedef struct WSAData { // Phiên bản hiện tại WORD wVersion; wHighVersion; // Phiên bản có thể hỗ trợ WORD char szDescription[WSADESCRIPTION_LEN + 1]; // Ghi chú szSystemStatus[WSASYS_STATUS_LEN + 1]; // Tr ạng thái hệ char thống unsigned short iMaxSockets; // Không s ử dụng từ Version 2 trở đi // Không s ử dụng từ Version 2 trở đi unsigned short iMaxUdpDg; lpVendorInfo; // Không s ử dụng từ Version 2 trở đi char FAR * } WSADATA, FAR * LPWSADATA; Và cuối cùng là hàm hủy Winsock khi kết thúc ch ương trình. nt WSACleanup (void); Chương trình đầu tiên: #include "stdafx.h"
- using namespace std; int _tmain(int argc, _TCHAR* argv[]) { WSADATA SData; int iResult = WSAStartup(0x0202,&SData); if (iResult!=0){ cout dùng địa chỉ IP để truyền dữ
- liệu) - AF_NETBIOS: NetBIOS (Giao th ức dùng tên máy để truyền dữ liệu) - AF_APPLETALK: AppleTalk - AF_ATM: ATM … Và ở trong Tut này mình chỉ nghiên cứu tới TCP/IP. * type: Quy định giao thức vận chuyển dữ liệu Ví dụ với giao thức TCP/IP thì có 2 giao thức cốt lõi là UDP và TCP: - SOCK_DGRAM: Hay là giao th ức UDP. Khi chương trình chúng ta dùng UDP để truyền dữ liệu thì chuyện gì sẽ xảy ra giữa bên gởi và bên nhận? Bên gửi cứ gửi và gửi và nó không hề quan tâm tới vấn đề bên nhận có nhận được nó hay không? => Ưu điểm: Tốc độ truyền dữ liệu nhanh. => Nhược điểm: Khả năng sai, mất dữ liệu sẽ rất lớn. Vậy dùng UDP khi nào? Những ứng dụng cần dữ liệu tức thời nh ư: - Chương trình nghe nhạc trực tuyến. Vấn đề sai bit (vấp khi nghe nhạc) không quan trọng mấy vì yêu cầu của nó l à đảm bảo tốc độ nhanh. - Chương trình Chat c hẳn hạn. - Hoặc GameOnline (thỉnh thoảng bạn bị tr ường hợp LAG chính là do bị mất dữ liệu trên đường truyền đó) - SOCK_STREAM: Đây là giao th ức TCP. Nó ngược với UDP vì nó đảm bảo giữa bên gửi và bên nhận dữ liệu phải chính xác. Vì vậy 2 bên sẽ phải bắt tay rất nhiều lần khi truyền đ ược dữ liệu (ví dụ như bên gửi sẽ gửi n gói tin (packet), bên nhận sẽ kiểm tra có bị mất hay sai gói tin nào hay không, nếu đủ thì nó sẽ yêu cầu bên gửi gửi tiếp n gói tin tiếp theo, ng ược lại thì nó sẽ yêu cầu gửi lại) => Ưu điểm: Chất lượng gởi tin cậy. => Nhược điểm: Chậm hơn UDP. Những ứng dụng như WEB, MAIL, FTP,… - SOCK_RAW: Là giao thức để kiểm soát mạng, kiểm tra kết nối… Ví dụ: Start -> Run -> CMD: “ping diendantinhoc.com”. Nếu bạn nhận được Reply có nghĩa là giữa máy tính của bạn với máy chủ “diendantinhoc.com” có “thông mạng” với nhau. Và gói tin mà bạn PING chính là SOCK_RAW (ICMP Packet)
- * protocol: Chỉ định rõ lại giao thức mà thôi. Vì SOCK_RAW có 2 protocol là ICMP và RAW nên nó cần điều này - SOCK_DGREAM -> protocol là: IPPROTO_UDP - SOCK_STREAM -> protocol là: IPPROTO_IP - SOCK_RAW -> protocol có thể là: IPPROTO_RAW hay IPPROTO_ICMP Các bạn có thể tham khảo thêm bảng thể hiện các thuộc tính của hàm SOCKET:
- 3. Một số hàm lấy thông tin về mạng
- a. Lấy thông tin Socket int WSAEnumProtocols ( LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, LPDWORD lpdwBufferLength ); lpiProtocols: NULL lpProtocolBuffer: Ki ểu dữ liệu trả về lpdwBufferLength: Kích thước của kiểu dữ liệu Tuy nhiên việc sử dụng hàm này còn hơi rườm rà. Ví dụ: WSAEnumProtocols(NULL,NULL,&size); // -> Lấy kích thước kiểu dữ liệu WSAPROTOCOL_INFO *lpProtocolBuffer; lpProtocolBuffer = (WSAPROTOCOL_INFO*) malloc(size); WSAEnumProtocols(NULL, lpProtocolBuffer,&size); b. Lấy tên máy tính c ủa mình int gethostname(char* name, int namelen); Ví dụ: char lpMyPCName[10]; gethostbyname(lpMyPCName,10) cout
- Trong đó typedef struct hostent { char FAR* h_name; // Tên máy tính char FAR FAR** h_aliases; // Bí danh máy tính // Kiểu IP (AF_INET) short h_addrtype; short h_length; // Kích thư ớc IP char FAR FAR** h_addr_list; // Danh sách c ác địa chỉ IP // 1 host có thể có 1 hoặc nhiều IP } HOSTENT, Ví dụ như: char lpHostName[100]; hostent *MyPC; gethostname(lpHostName,100); MyPC = gethostbyname(lpHostName); e. Lấy tên máy theo địa chỉ IP Tương tự nhưng ngược lại. hostent* FAR gethostbyaddr(const char* addr, int len, int type); Ví dụ lấy thông tin Yahoo (có địa chỉ IP: 216.109.112.135) hostent *Yahoo; u_long YahooAddr = inet_addr("216.109.112.135"); Yahoo = gethostbyaddr((char*)&YahooAddr,4,AF_INET);
- Chương trình mẫu khởi tạo Socket: III. ĐỊA CHỈ MẠNG Thread trước mình đã giới thiệu về SOCKET tuy nhiên mình chỉ nói khởi tạo, còn việc để gửi hay nhận gói tin cần phải thêm thông tin về địa chỉ IP cho nó nữa. Ở Thread này mình sẽ tạm gác lại về SOCKET và C/C++ để đi sâu vào kiến thức cơ bản mạng cụ thể l à địa chỉ IP. Bởi vì bạn muốn lập trình được chương trình truyền dữ liệu trên protocol TCP/IP mà không biết về IP thì hơi vô lý. Do đó cái thread này có phần đi ngoài lề về lập trình 1 xíu. 1. Địa chỉ IP Một HOST muốn giao dịch trên mạng sử dụng giao thức TCP/IP thì cần phải có 1 địa IP duy nhất để xác địch chính nó (nh ư địa chỉ nhà bạn) trên môi trường mạng. Hiện nay có 2 loại địa chỉ IP. Đó là IPv4 (4 bytes) và IPv6. Tuy nhiên IPv6 vẫn chưa thể thay thế cho IPv4 được bởi vì số thiết bị dùng IPv4 quá nhiều. Cài đặt địa chỉ IP ở đâu ?
- Hiện này IPv4 sử dụng rất nhiều và nó sẽ dùng 4bytes (32bit) để biểu diễn 1 địa chỉ Cấu trúc địa chỉ bao gồm 2 phần là: Network_id và Host_id 2. Các lớp địa chỉ IP
- Địa chỉ IP có thể phân tới 5 lớp (dựa trên Network_id) nhưng thực tế thì chỉ có 3 lớp A,B,C được sử dụng. a. Lớp A - Số byte làm Network_id: 1 byte (địa chỉ đầu tiên từ 0 – 127) - Số byte là Host_id: 3 bytes còn l ại (trong 1 Network không đ ược trùng) - Subnet Mask: 255.0.0.0 - Địa chỉ BroadCast (đại diện cho tất cả các máy trong đ ường mạng -> Khi gởi tới địa chỉ này thì mọi host trong mạng sẽ nhận). x x x.255.255.255. - Địa chỉ Network (đai diện bất kỳ một máy trong mạng – thường dùng để kiểm soát, định tuyến,…) x x x.0.0.0 Ví dụ: 10.1.1.1 * Trong lớp A có đường mạng 127.0.0.0 là đường mạng không sử dụng, nó được sử dụng để kiểm tra giao thúc TCP/IP. Ví dụ bạn ping 127.0.0.1 th ì luôn nhận reply vì đây là địa chỉ máy tính của bạn cho d ù IP của bạn ở lớp nào đi chăng nữa địa chỉ này chỉ sử dụng tại máy tính của bạn mà thôi. b. Lớp B - Số byte làm Network_id: 2 byte (địa chỉ đầu tiên từ 128 – 191) - Số byte là Host_id: 2 bytes còn l ại (trong 1 Network không đ ược trùng) - Subnet Mask: 255.255.0.0 - Địa chỉ BroadCast (đại diện cho tất cả các máy trong đ ường mạng -> Khi gởi tới địa chỉ này thì mọi host trong mạng sẽ nhận). x x x.x x x.255.255. - Địa chỉ Network (đai diện bất kỳ một máy trong mạng – thường dùng để kiểm soát, định tuyến,…) x x x.x x x.0.0 Ví dụ: 172.11.22.3 c. Lớp C - Số byte làm Network_id: 3 byte (địa chỉ đầu tiên từ 192 – 223) - Số byte là Host_id: 1 bytes còn l ại (trong 1 Network không đ ược trùng) - Subnet Mask: 255.255.255.0 - Địa chỉ BroadCast (đại diện cho tất cả các máy trong đ ường mạng -> Khi gởi tới địa chỉ này thì mọi host trong mạng sẽ nhận). x x x.x x x.x x x.255. - Địa chỉ Network (đai diện bất kỳ một máy trong mạng – thường dùng để kiểm soát, định tuyến,…) x x x.x x x.x x x.0 Ví dụ: 192.168.23.3 d. Network_id và Host_id có ý nghĩa gì? Ví dụ địa chỉ IP lớp C:
- IP: 192.168.10.4 Thì sẽ có: Mask: 255.2255.255.0 BroadCast: 192.168.10.255 Network: 192.168.10.0 Ví dụ mình sẽ có thêm 2 HOST với 2 địa chỉ IP c ùng lớp C nữa là: 192.168.10.3 và 192.168.11.2 Như vậy: - Nếu mình ở tại máy tính có địa chỉ 192.168.10.4 (start -> run -> “cmd”) + ping 192.168.10.3 thì mình sẽ nhận được reply tức là 2 địa chỉ này “thông mạng” vì cùng Network là: 192.168.10.0 + ping 192.168.11.2 thì kết quả sẽ là “request time out”. (Không liên lạc được) bởi vì 2 host này ở 2 mạng khác nhau (192.168.10.0 và 192.168.11.0). Như vậy: - Network_id sẽ quy định host trong đó thuộc “đ ường mạng” nào. Và các host chỉ thấy nhau khi cùng “đường mạng” - Host_id: dùng để phân biệt host với tất cả các host khác trong mạng Tiếp tục… Nếu để 2 đường mạng như trên 192.168.10.0 và 192.168.11.0 có thể “liên lạc” với nhau thì sao? Người ta cần định tuyến mạng với thiết bị mạng có tên là Router (Modem ADSL c ũng là 1 router) hoặc một máy chủ Sever có dịch vụ RAS (routing), hoặc một Proxy…. => Router là m ột thiết bị có 2 card mạng và sẽ có ít nhất 2 địa chỉ IP. Trong hình trên thì Card mạng thứ 2 của hai router phải thiết lập sao cho có c ùng đường mạng để “li ên lạc với nhau”. Ví dụ như là 192.168.12.0. Như vậy LAN 1 sẽ liên lạc được với LAN 2 thông qua 2 router trên hình.
- 3. Tại sao lại phân loại địa chỉ IP - Là do nhu cầu của từng môi trường mạng. Ví dụ ở lớp A: - Network_id sẽ là 1 bytes (8 bits) -> Nó sẽ có 2^7 = 127 (đường mạng) + Tại sao là 8 bit nhưng lại là 2^7 ? -> Là vì số bit từ làm Subnet là 0 -> 7 (biểu diễn tới 2^7) - Host_id là (24 bits): -> 2^24 – 2 = 16.777.214 (Hosts) (trừ 2 địa chỉ Broadcast v à Subnet) => Ở lớp A số đường mạng ít nhưng số host trên đường mạng nhiều -> thích hợp với các công ty lớn Ví dụ ở lớp B: - Network_id sẽ là 2 bytes (16 bits) -> Nó sẽ có 2^15 = 16.384 (đường mạng) - Host_id là (16 bits): -> 2^16 – 2 = 65.534 (hosts) => Số đường mạng lớp B và số host vừa nhau Ví dụ ở lớp C: - Network_id sẽ là 3 bytes (24 bits) -> Nó sẽ có 2^23 = 2.097152 (đ ường mạng) - Host_id là (8 bits): -> 2^8 – 2 = 254 (Hosts) => Số đường mạng lớp C rất nhiều những host mỗi đ ường mạng lại rất ít. Và có lẽ lớp C là lớp được sử dụng nhiều trong mạng LAN bởi lẽ với con số PC dưới 100 trên phòng máy thì l ớp C là lựa chọn hay nhất. Hy vọng tới đây các bạn sẽ hình dung 1 chút ít gì đó về địa chỉ IP. 4. IP LAN và IP WAN a. IP LAN (PRIVATE IP): Trong dãy các IP đó thì người ta trích mỗi lớp một khoảng làm IP LAN và nó chỉ có tác dụng giao dịch trong mạng LAN. Chúng ta có thể đặt IP cho card mạng với những khoảng dưới đây. Lớp A: 10.0.0.0 đến 10.255.255.255 (số l ượng đường mạng 1) Lớp B: 172.16.0.0 đến 172.31.255.255 (số l ượng đường mạng 16) Lớp C: 192.168.0.0 đến 192.168.255.255 (số l ượng đường mạng 256)
- b. IP WAN (PUBLIC IP): Là các IP còn lại không thuộc IP LAN. Đây là IP mà cả thế giới thấy được, và muốn có bạn phải mua hoặc đ ược ISP cung cấp (về bản chất thì ISP cũng mua các khoảng IP này và cung c ấp các dịch vụ Internet nh ư ADSL, mỗi IP là 1 thuê bao ADSL). Ví dụ máy tính của bạn có IP là: 172.16.10.2 - Tại một nơi nào đó trên thế giới bạn truy cập tới địa chỉ này -> Không thể được vì nó là IP LAN, một IP chỉ có giá trị trong mạng LAN ) - Chúng ta muốn thế giới thấy được chúng ta thì chúng ta phải có IP WAN. Ở gia đình mạng ADSL của có thể có rất nhiều máy tính bên trong mang IP LAN. Nhưng có 1 thiết bị có IP WAN là ADSL Router và m ọi người trên thế giới thấy được nó, tuy nhiên đây là địa chỉ động và bị thay đổi li ên tục… do đó việc truy cập cũng rất khó. Bạn có thể nghiên cứu thêm vấn đề này bằng cách vào google và gõ t ừ khóa “NAT” ("Network Address Translation") 5. Địa chỉ IP trong thực tế a. Một số địa chỉ IP cần thiết Hãy xem mô hình mạng của mình. Bạn vào start->run->”cmd” gõ lệnh “ipconfig /all” IP Address. . . . . . . . . . . . : 192.168.1.254 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 192.168.1.1 DNS Servers . . . . . . . . . . . : 203.113.131.1 203.113.131.2 - Default Gateway: Cổng ra của gói tin m à ta muốn gửi đi nếu địa chỉ đến của gói tin đó khác đường mạng. Và đây thư ờng là địa chỉ của những thiết bị làm nhiệm vụ định tuyến (Routing) như ADSL Modem Địa chỉ IP 192.168.1.1 (IP LAN) chính là địa chỉ của cái ADSL Moderm. R õ ràng nó phải cùng đường mạng với máy tính của mình (đường mạng: 192.168.1.0)
- - DNS Servers: Là dịch vụ phân giải tên miền. Khi ta truy cập internet thì nó sẽ chuyển đổi giữa tên miền -> IP: Ví dụ như mình gõ: http://www.google.com --> DNS SERVER-> http://72.14.207.99 DNS SERVER như là một “cơ sở dữ liệu khổng lồ” m à mỗi record sẽ là một tên miền và 1 IP. Do được phân cấp theo dạng cây “vn -> com -> google” nên khả năng tìm kiếm của DNS rất nhanh. DNS của mạng FTP là 203.113.131.1 (IP WAN) và 1 cái d ự phòng là 203.113.131.2. Dịch vụ thì VNN (203.162.4.190, 203.162.4.191, 203.162.0.181,… ) và c ủa Viettel thì khác, cũng có thể DNS là GateWay nhưng thực chất trong ADSL Router nh à cung cấp ISP đã cài đặt DNS truy vấn tới các địa chỉ trên rồi. b. Truy cập WEB trên Internet - Để minh họa hơn về IP,mình sẽ lấy 1 ví dụ về truy cập WEB trên Internet. - Bắt đầu khi ta gõ: http://www.google.com từ PC có địa chỉ 192.168.1.254
- - Host 192.168.1.254 sẽ nhờ DNS SERVER (203.113.131.1) phân giải dùm google.com có địa chỉ IP là bao nhiêu??? (72.14.207.99) - Và lúc này có kết quả tương đương: http://72.14.207.99 - Sau đó host sẽ truy cập tới 72.14.207.99 nh ưng thực sự là nó nhờ Gateway (ADSL Router 192.168.1.1) vì khác đường mạng. - ADSL Router hiểu như là 1 PC có 2 card mạng + 1 cái mang địa chỉ IP LAN để giao dịch bên trong đường mạng 192.168.1.0. + 1 cái mang địa chỉ IP WAN thay đổi mỗi lần khởi động do ISP cung cấp (ví dụ như VNN hay FTP, Viettel…) để giao dịch bên ngoài Internet. + Và nhiệm vụ của ADSL Router là sẽ định tuyến và xác định đường đi từ Việt Nam qua Singapo (Trung quốc) -> … -> Mỹ để truy cập tới địa chỉ 72.14.207.99. Và lấy nội dung trang WEB về.
- - Cuối cùng nó sẽ trả lại cho host mang địa chỉ 192.168.1.2 54 và trang WEB của google sẽ hiện ra trên web browser… Tham khảo bài viết "Nguyên lý hoạt động của giao thức TCP/IP và Internet" 6. Biểu diễn địa chỉ IP trong Winsock Quay lại về vấn đề WINSOCK Tại sao IP quan trọng trong lập trình mạng như vậy, bởi vì IP rất quan trọng trong mô hình TCP/IP. - 1 Server phải có 1 IP để lắng nghe kết nối trên địa chỉ IP của mình. - 1 Client muốn kết nối với Server thì phải có IP của Server… Trong Winsock người ta sử dụng cấu trúc sockaddr_in để biểu diễn địa chỉ IP. struct sockaddr_in{ short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; Trong đó: - sin_family: AF_INET - sin_port: Là port (cổng logic) để lắng nghe kết nối. -> 1 ứng dụng Server hay Client rất cần 1 port để li ên lạc trên mạng. Bởi vì card mạng sẽ thông qua số hiệu port này để nhận biết được gói tin đang nhận (hay gửi đi) của ứng dụng nào? - Các port dưới 1024 là những port dành riêng cho các dịch vụ như: Một số port như: 80 (Web), 20,21 (FTP), Mail (25 SMTP, 993 POP3), 53 (DNS), 22 (SSH), 23 (Telnet)... Ví dụ như ta gõ http://www.google.com - http là giao thức WEB => Port 80. - www.google.com => IP: 72.14.207.99 Như vậy tại Client sẽ khởi tạo 1 port (lớn hơn 1024) kết nối tới địa chỉ 72.14.207.99 qua port 80. Dựa vào số port người quản trị có thể kiểm soát đ ược mạng ví dụ như chỉ có
- lướt WEB (mở port 80, 53) nhưng chặn hết các port khác => Bạn không thể chat và gameonline mặc dù có Internet. Với số nguyên u_short (16bit) có nghĩa có thể chọn tới 2^16 = 65535 port sử dụng giao dịch trên mạng. à ứng dụng của chúng ta phải chọn port lớn hơn 1024 nếu hông muốn viết 1 Sever nh ư WEB hay FTP,… - sin_addr: là m ột struct để xác định địa chỉ IP (có thể là IP của Server hoặc IP của chính mình,…) - Nếu sin_addr.s_addr = INADDR_ANY; Thì IP sẽ chính là IP của mình. Các Server thường dùng để chọn địa chỉ IP của mình và lắng nghe kết nối.. - Nếu sin_addr.s_addr = inet_addr(“x x x.x x x.x x x.xx”); Thì IP sẽ là IP chỉ định theo chuỗi. Client phải chỉ định đ ược IP của Server mới kế nối đ ược. - sin_zero Để dành 8 byte (không sử dụng). Ví dụ: sockaddr_in ip; ip.sin_family = AF_INET; ip.sin_port = htons(99999); ip.sin_addr.s_addr = inet_addr("10.0.0.2"); IV. ỨNG DỤNG CLIENT - SERVER 1. Ứng dụng Client - Server là gì? Trước tới giờ, các bạn lập trình với mục đích là tạo ra được một ứng dụng. Nhưng ứng dụng đó chỉ hoạt động độc lập 1 mình riêng lẽ. Mục tiêu lập trình mạng sẽ đưa ra những ứng dụng dạng Client – Server. Tức là sẽ có 2 loại ứng dụng chính đó l à Client và Server. Quy trình hoạt động của ứng dụng Server – Client như sau: - Server có nhiệm vụ của là lắng nghe, chờ đợi kết nối từ Client trên địa chỉ IP của mình với PORT được quy định sẵn. Khi client gởi dữ liệu tới Server th ì nó phải giải quyết một công việc l à nhận dữ liệu đó -> xử lý -> trả kết quả lại cho Client. - Client là ứng dụng được phục vụ, nó chỉ gởi truy vấn và chờ đợi kết quả từ Server. Trong mô hình TCP/IP có 2 giao th ức là TCP và UDP và 2 giao th ức này sẽ quyết định cách thức hoạt động của Client - Server như thế nào?
- a. Hoạt động của Client – Server trong giao thức TCP (SOCK_STREAM)
- b. Hoạt động của Client – Server trong giao thức UDP (SOCK_DGRAM)
CÓ THỂ BẠN MUỐN DOWNLOAD
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn