Kiểm tra lỗi và xử lý
Hầu hết giá trị không thành công trả lại là SOCKET_ERROR ( -1 ).
Nếu bạn sử dụng 1 hàm Winsock và có lỗi xảy ra, bạn có thể sử dụng hàm WSAGetLastError() để lấy mã lỗi vừa xảy ra :
int WSAGetLastError (void);
Ví dụ :
Mã:
#include <winsock2.h> void main(void) { WSADATA wsaData; // Khởi tạo Winsock phiên bản2.2 if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0) { // Chú ý rằng, hàn WSAStartup() thất bại thì ta không thể // sử dụng hàm WSAGetLastError() để lấy mã lỗi được. Thay // vào đó, ta lấy giá trị trả về của hàm này. printf("WSAStartup failed with error %d
", Ret); return; } // Setup Winsock communication code here // When your application is finished call WSACleanup if (WSACleanup() == SOCKET_ERROR) { printf("WSACleanup failed with error %d
", WSAGetLastError()); } }
Địa chỉ IP
Địa chỉ 1 giao thức
- Trong chương này, chúng ta thảo luận cách sử dụng các hàm Winsock để thiết lập kết nối sử dụng giao thức Internet ( Internet Protocol - IP ). Winsock là 1 giao diện giao thức độc lập. - IP được sử dụng trên hầu hết các OS , các mạng cục bộ - Lan , hay các mạng diện rộng - WAN , như Internet.- IP là giao thức phi kết nối và truyển tải dữ liệu không đảm bảo.
- Có 2 loại giao thức tốt hơn là TCP ( Giao thức điều khiển truyền tải ) và UDP ( Giao thức gói dữ liệu người dùng ). Cả 2 giao thức đều sử dụng IP để truyển tải dữ liệu nên được gọi là TCP/IP và UDP/IP.
Địa chỉ IPv4
- Theo IPv4 , máy tính được thể hiện dưới dạng 1 số 32 bit.
- Khi 1 máy khách muốn kết nối với 1 máy chủ, nó phải biết địa chỉ của máy chủ và công kết nối.
- Khi 1 máy chủ muốn nghe các yêu cầu từ máy khách chuyển tới , chúng phải chỉ định 1 địa chỉ IP và 1 cổng kết nối cụ thể.
- Trong Winsock , thông tin địa chỉ IP và cổng dịch vụ được chứa trong cấu trúc SOCKADDR_IN :
Mã:
struct sockaddr_in{short sin_family;u_short sin_port;struct in_addr sin_addr;char sin_zero[8];};
- sin_family : phải set tới AF_INET , chỉ định cho Winsock biết sử dụng địa chỉ IP.
- sin_port : để xác định dịch vụ của server.
- sin_addr : Được sử dụng để lưu trữ 1 địa chỉ IPv4 kiểu dữ liệu u_long .
- Nếu sin_addr.s_addr = INADDR_ANY , thì IP là IP của chính mình. Các server thường ùng IP của chính nó để lắng nghe kết nối.
- sin_zero : Là vùng đệm để cấu trúc SOCKADDR_IN có cùng kích cỡ với SOCKADDR. Nó hữu dụng khi sử dụng hàm inet_addr() để convert 1 đại chỉ IP dạng chấm sang dạng u_long 32 bit.
Mã:
unsigned long inet_addr(const char FAR *cp );
- cp : Là chuỗi chứa địa chỉ IP dạng num-dot.
- Nếu cp = NULL , hàm trả về INADDRY_ANY.
- Nếu cp = " " , hàm trả về 0.
- Nếu convert thất bại, hàm trả về INADDR_NONE.
Thứ tự bytes
Các vi xử lý khác nhau miêu tả các số dưới dạng big-endian và little-endian, phụ thuộc vào chúng được thiết kế như thế nào. Ví dụ, vi xử lý Intel x86 miêu tả các số multibyte dưới dạng little-endian : Các byte sắp xếp từ ít quan trọng nhất tới quan trọng nhất. Khi địa chỉ IP và số cổng được thể hiện dưới dạng số multibyte trên máy tính, chúng được miêu tả ở dạng host-byte. Tuy nhiên, khi địa chỉ IP và số cổng qua 1 mạng , mạng chuẩn mạng Internet quy định rằng các giá trị multibyte phải được miêu tả dưới dạng big-endian ( quan trọng nhất tới ít quan trọng nhất ) , tương đương với dạng network-byte.
Trên máy tinh : little-endian ( host-byte ).
Chuẩn mạng Internet : big-endian ( network-byte ).
Một vài hàm được sử dụng để chuyển các số multibyte dạng host-byte sang network-byte và ngược lại.
Bốn hàm API chuyển số host-byte sang network-byte :
Mã:
u_long htonl(u_long hostlong); int WSAHtonl(SOCKET s,u_long hostlong,u_long FAR * lpnetlong); u_short htons(u_short hostshort); int WSAHtons(SOCKET s,u_short hostshort,u_short FAR * lpnetshort);
Tiếp là 4 hàm chuyển từ network-byte về host-byte :
Mã:
u_long ntohl(u_long netlong); int WSANtohl( SOCKET s, u_long netlong, u_long FAR * lphostlong); u_short ntohs(u_short netshort); int WSANtohs( SOCKET s, u_short netshort, u_short FAR * lphostshort);
Ví dụ
Mã:
SOCKADDR_IN InternetAddr;INT nPortId = 5150; InternetAddr.sin_family = AF_INET; // Chuyển địa chỉ Internet dạng num-dot 136.149.3.29// về dạng nguyên 4-byte, và điền nó vào sin_addr InternetAddr.sin_addr.s_addr = inet_addr("136.149.3.29"); // Biến nPortId lưu trữ ở dạng host-byte order. Chuyển// nPortId về dạng network-byte order, và điền nó vào sin_port. InternetAddr.sin_port = htons(nPortId);
Thông qua phân tích dữ liệu Google từ 86 quốc gia, mới đây, một công ty tại Anh đã công bố bảng xếp hạng kích tấc "cậu nhỏ" của các nước trên thế giới. Kết quả, hầu hết các nước xếp ở nhóm đầu của...
"Chim" của chàng trai Việt thuộc...