Tải bản đầy đủ

Bài giảng môn Lập trình Mạng

Chương 1:

TỔNG QUAN VỀ LẬP TRÌNH MẠNG

I. Họ giao thức TCP/IP
1. Mục tiêu
_ Cung cấp dịch vụ truyền thông liên mạng, che dấu chi tiết kiến trúc liên mạng, che dấu chi tiết phần
cứng.
_ Kiến trúc phân lớp.

2. Địa chỉ IP
a) Khái niệm
_ Địa chỉ luận lý (địa chỉ cấp phát động hoặc tĩnh): xác định duy nhất một máy trên mạng, khác với địa
chỉ card mạng.
_ Địa chỉ vật lý (địa chỉ card mạng): do nhà sản xuất cấp phát.
_ Phiên bản:
• Ipv4: 32 bit, dạng biểu diễn số chấm thập phân (ví dụ: 192.168.10.1).
• Ipv6: 128 bit.

b) Phân lớp địa chỉ
_ Xác định bởi những bit nhận dạng (Class ID):


– Sự tương quan giữa lớp và kích thước mạng:

_ Các địa chỉ IP đặc biệt:

_ Các vùng địa chỉ IP dành riêng (Private Network):
• 10.0.0.0 – 10.255.255.255.255
• 172.16.0.0 – 172.31.255.255
• 192.168.0.0 – 192.168.255.255

3. Một số giao thức
a) Lớp Internet (Internet Layer)
_ Giao thức Internet (IP – Internet Protocol).
_ Giao thức Kiềm soát Thông điệp Internet (Internet Control Message Protocol – ICMP).
_ Giao thức Nhóm Thông điệp Internet (Internet Group Message Protocol – IGMP).
_ Giao thức Phân giải Địa chỉ (Address Resolution Protocol – ARP), giao thức Chuyển đổi Địa chỉ
(Address Reverse Protocol – ARP): chuyển đổi địa chỉ vật lý, luận lý.

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


b) Lớp Giao vận (Transport Layer)
_ Cung cấp dịch vụ truyền thông giữa các tiến trình.
_ Thông tin xác định tiến trình:
• Địa chỉ IP.
• Cổng (16 bit):
 0 – 1023: well-know port, IANA (Internet Assigned Numbers Authority).
 1024 – 49151: registered port.
 49152 – 65535: dynamic port.
_ Giao thức Kiểm soát Truyền thông (Transmission Control Protocol – TCP):
• Có thiết lập cầu nối: full duplex.
• Tin cậy: đúng trình tự, không thất thoát, không trùng lấp.
• Byte stream: đệm dữ liệu (nơi lưu trữ dữ liệu trước khi gửi; ví dụ: nếu đệm là 1 KB, gói dữ liệu
là 2 KB thì chỉ có 1KB được chuyển phải gửi lại thêm 1 KB nữa).
_ Giao thức Dữ liệu Người dùng (User Datagram Protocol – UDP):
• Không thiết lập cầu nối.
• Không tin cậy.
• Dạng truyền thông (broadcast).


• Dữ liệu Người dùng (datagram).

c) Lớp Ứng dụng (Application Layer)
_ Cung cấp việc vận chuyển dữ liệu trong suốt giữa các hệ thống đầu cuối (end systems).

II. Ứng dụng mạng
_ Truyền tải tập tin (File Transfer).
_ Trình duyệt web / server (Web Browser / Server).
_ Thư điện tử (Electric Mail).
_ Truyền tải giọng nói (Voice over IP).
_ Xem phim, nghe nhạc trực tuyến (Audio / Video Online).
_ Hội họp từ xa (Remote Conferencing).
_ Trò chơi trực tuyến (Game Online).
_…

III. Mô hình ứng dụng
_ Mô hình 2 tầng (2-tiers): Client / Server.
_ Mô hình đa tầng (N-tiers).
_ Mô hình hàng ngang (Peer to Peer).

IV. Giao diện lập trình socket
1. Window Socket API
_ Khái quát:
• Phát triển theo đặc tả giao diện Phân phối Phần mềm Berkeley (Berkeley Soft ware Distribution
– BSD Socket).
• Bổ sung các tính năng hoạt động của môi trường Windows.
• Hiện thực ở dạng thư viện liên kết động: wsock32.dll (winsock.h), ws2_32.del (winsock.h).
• Thư viện lập trình giao tiếp với giao thức mạng.
_ Dữ liệu: socket, địa chỉ IP, thông tin máy.
_ Các hàm: liên kết thư viện truy xuất thông tin, chuyển đổi dữ liệu, làm việc với socket.

2. Tiếp cận hướng đối tượng
a) MFC
_ Thư viện hỗ trợ của Microsoft:
• Che giấu chi tiết sử dụng các hàm Winsock API.
• Hỗ trợ xây dựng ứng dụng Internet.
_ Windows Sockets: CasyncSocket, Csocket, CsocketFile.
_ Mở rộng: Win32 Internet Extensions Winlnet:
• ElnternetSession.
• ElnternetConnection: CftpConnection, CgopherConection, ChttConnection.
• CgopherLocation.

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


• ElnternetFile.
• EfileFmd.

b) .NET
_ System.Net:
• DNS.
• IPAddress.
• EndPoint.
• IPHostEntry.
• Socket Address.
• WebRequest, WebResponse.
• WebClient.
•…
_ System.Net.Socket:
• Socket.
• SocketException.
• TcpClient, TcpListener.
• UdpClient.
•…
_ System.Net.Mail:
• Enet.
•…

c) Java
_ Java.Net:
• InetAddress.
• Socket, ServerSocket.
• SocketException.
• URI+, URL.
_ Javamail.

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


Chương 2:

CĂN BẢN LẬP TRÌNH WINSOCK

I. Socket
1. Khái niệm
_ Cơ chế trừu tượng dùng cho quá trình truyền thông giữa các tiến trình.
_ Tương ứng với cấu trúc chứa các thông tin cần cho quá trình truyền thông giữa các tiến trình (IP, port).

2. Quản lý socket
_ Cấu trúc dữ liệu do hệ điều hành quản lý.
_ Ứng dụng sử dụng thông qua handle.

3. Phân loại
_ Stream Socket: TCP Socket.
_ Datagram Socket: UDP Socket.
_ Raw Socket.

II. Phân nhóm hàm thư viện
_ Liên kết thư viện, kết thúc.
_ Truy xuất thông tin.
_ Chuyển đổi dạng dữ liệu.
_ Các hàm thao tác trên socket:
• Tạo socket, đóng socket.
• Thiết lập cầu nối.
• Gửi, nhận dữ liệu.

III. Liên kết thư viện
_ Liên kết thư viện: int WSAStartup (WORD wVersionRequested, LPWSADATA lpwaData);
_ Kết thúc: int WSACleanup();
_ Truy xuất mã lỗi sai: int WSAGetLastError();
_ Lưu ý:
• File StdAfx.h: #include
• Lớp ứng dụng:
bool CDDemoApp :: InitInstance()
{
...
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return false;
}
...
return false;
}

IV. Truy xuất thông tin
1. Thông tin máy
_ Các phương thức:
• int gethost name (char FAR* name, int len);
• PHOSTENT gethostbyname (const char FAR* hostname);
• PHOSTENT gethostbyaddr (const char FAR* addr, int len, int af);
_ Ví dụ:
char sethostName [MAX_LEN];
if (gethostname (sethostName, MAX_LEN) != SOCKET_ERROR)
{ //… }
else { //… }

_ Cấu trúc thông tin máy:
• struct hostent
{

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


char FAR* h_name;
char FAR* FAR* h_aliases;
short h_addtype;
short h_lenght;
char FAR* FAR* h_addr_list;
#define h_addr h_addr_list[0];
};
• PHOSTENT pHostEnt = gethostbyname (set);
if (pHostEnt != NULL) { //… }

2. Thông tin dịch vụ
_ Cú pháp:
PSERVENT getservbyname (constchar char FAR* name, const FAR* proto);

V. Chuyển đổi thông tin dữ liệu
1. Chuyển đổi trật tự byte
_ Trật tự byte:
• Lưu trữ số nguyên trên máy tính:
Host Byte Order
Little-Endian
Big-Endian
short
12AB
AB12
12AB
long
12AB34CD
CS34AB12
12AB34CD
• Quy ước lưu trữ số nguyên trên mạng (Network Byte Order): Big-Endian.
_ Các hàm chuyển đổi:
• u_short ntohs (u_short);
• u_long ntohl (u_long);
• u_short htons (u_short);
• u_long htonl (u_long);

2. Chuyển đổi dạng địa chỉ
_ Dạng biểu diễn địa chỉ IPv4:
• Số nguyên 4 byte.
• Chuỗi dấu chấm thập phân (Dotted Decimal).
_ Các hàm chuyển đổi:
• unsigned long inet_addr (const char FAR* CD);
• char FAR* inet_ntoa (struct in_addr in);
_ Cấu trúc địa chỉ:
struct in_addr
{
union
{
struct { u_char s_b1, s_b2, s_b3, s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define
#define
#define
#define
#define
#define

s_addr S_un.S_addr // can be used for most tcp & ip code
s_host S_un.S_un_b.s_b2 // host on imp
s_net S_un.S_un_b.s_b1 // network
s_imp S_un.S_un_w.s_w2 // imp
s_impno S_un.S_un_b.s_b4 // imp #
s_lh S_un.S_un_b.s_b3 // logical host

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


};

_ Ví dụ:
//…
PHOSTENT pHost = gethostbyname (“…”);
if (pHost != NULL)
{
IN_ADDR inAddr;
memcpy (&inAddr, pHost->h_addr, 4);
// inAddr.s_addr = pHost->h_addr;
Cstring sAddress = inet_ntoa (inAddr);
//…
}

memcpy (&inAddr, pHost->h_addr, 4);

VI. Các hàm socket
1. Quy trình sử dụng
a) Có thiết lập cầu nối

b) Không thiết lập cầu nối

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


2. Chi tiết sử dụng
a) Tạo socket
_ Cú pháp: SOCKET socket (int af, int type, int protocol);
_ Thông số:
• af: họ địa chỉ AF_INET.
• type: loại địa chỉ – SOCK_STREAM (có thiết lập cầu nối – TCP), SOCK_DGRAM (không thiết
lập cầu nối – UDP).
• protocol: loại giao thức – 0.
_ Kết quả trả về:
• Thành công: handle của socket vừa tạo.
• Thất bại: INVALID_SOCKET.
_ Ví dụ:
SOCKET s; // socket descriptor
char lpszMessage[100]; // informational message
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
wsprintf (lpszMessage, “socket() generated error %d”,
WSAGetLastError());
else lstrcpy(lpszMessage, “socket() succeeded”);
MessageBox(NULL, lpszMessage, “Info”, MB_OK);

b) Đóng socket
_ Cú pháp: int closesocket(SOCKET s);
_ Thông số: s: handle máy muốn đóng.
_ Kết quả trả về: Thất bại: SOCKET_ERROR.

c) Gán thông tin socket
_ Cú pháp: int bind (SOCKET s, const struct sockaddr FAR* addr, int addrlen);
_ Thông số:
• s: handle của socket chờ gán thông tin.
• addr: địa chỉ cấu trúc dùng để chứa thông tin socket phía kết nối đến.
• addrlen: địa chỉ biến chứa kích thước cấu trúc bởi addr.
_ Cấu trúc thông tin socket:
struct sockaddr
{
u_short sa_family; // address family
char sa_data[14]; // up to 14 bytes of direct address
};
struct sockaddr_in
{
short sin_family; // address family
u_short sin_port; // service port
struct in_addr sin_addr; // Internet address
char sin_zero[8]; // filler

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


};

_ Ví dụ:
SOCKET s; // socket descriptor
char lpszMessage[100]; // informational message
SOCKADDR_IN addr; // Internet address
// create a stream socket
s = socket(AF_INET, SOCK_STREAM, 0);
if (s != INVALID_SOCKET)
{
// fill out the socket’s address information
addr.sin_family = AF_INET;
addr.sin_port = htons(1050);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// bind the socket to its address
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
{
wsprintf(lpszMessage, “ bind() generated error %d”,
WSAGetLastError());
MessageBox(NULL, lpszMessage, “Info”, MB_OK);
}
else { //... }
}
• Trường hợp không chỉ định port: sin_port = 0;
• Lấy thông tin socket: int getsockname (SOCKET s, struct sockAddr* addr, int*
addrlen);

d) Lắng nghe
_ Cú pháp: int listen (SOCKET s, int backlog);
_ Thông số:
• s: handle máy muốn đóng.
• backlog: kích thước hàng đợi kết nối.
_ Kết quả trả về: Thất bại: SOCKET_ERROR.
_ Ví dụ:
SOCKET s; // socket descriptor
char lpszMessage[100]; // informational message
SOCKADDR_IN addr; // Internet address
// create a stream socket
s = socket(AF_INET, SOCK_STREAM, 0);
if (s != INVALID_SOCKET)
{
// fill out the socket’s address information
addr.sin_family = AF_INET;
addr.sin_port = htons(1050);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// bind the socket to its address
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) != SOCKET_ERROR)
{
// listen for connections (queueing up to three)
if (listen(s, 3) == SOCKET_ERROR)
{
wsprintf(lpszMessage, “listen() generated error %d”,
WSAGetLastError());
MessageBox(lpszMessage, “Info”);
}
else { //... }
}
}

e) Tiếp nhận
_ Cú pháp: SOCKET socket (SOCKET s, struct sockAddr FAR* addr, int FAR*
addrlen);

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


_ Thông số:
• s: handle của socket chờ tiếp nhận “nói” (“lắng nghe”).
• addr: địa chỉ cấu trúc dùng để chứa thông tin socket phía kết nối đến.
• addrlen: địa chỉ biến chứa kích thước cấu trúc bởi addr.
_ Kết quả trả về:
• Thành công: handle của socket giao tiếp với phía kết nối đến
• Thất bại: INVALID_SOCKET.
_ Ví dụ:
SOCKET s; // socket descriptor
SOCKET clientS; // client socket descriptor
char lpszMessage[100]; // informational message
SOCKADDR_IN addr; // Internet address
SOCKADDR_IN clientAddr; // Internet address
IN_ADDR clientIn; // IP address
int nClientAddrLen;
// create a stream socket
s = socket(AF_INET, SOCK_STREAM, 0);
if (s != INVALID_SOCKET)
{
// fill out the socket’s address information
addr.sin_family = AF_INET;
addr.sin_port = htons(1050);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// bind the socket to its address
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) != SOCKET_ERROR)
{
// listen for connections (queueing up to three)
if (listen(s, 3) != SOCKET_ERROR)
{
// set the size of the client address structure
nClientAddrLen = sizeof(clientAddr);
// accept a connection
clientS
=
accept(s,
(LPSOCKADDR)&clientAddr,
&nClientAddrLen);
if (clientS == INVALID_SOCKET)
{
wsprintf(lpszMessage, “ accept() generated error
%d”,
WSAGetLastError());
MessageBox(lpszMessage, “Info”);
}
else
{
// copy the four byte IP address into an IP
address structure
memcpy(&clientIn, &clientAddr.sin_addr.s_addr, 4);
// print an informational message
wsprintf(lpszMessage,
“accept() ok: client IP address is %s, port is
%d”,
inet_ntoa(clientIn), ntohs(clientAddr.sin_port));
114 Part II n Basics of WinSock Programming
MessageBox(lpszMessage, “Info”);
...
}
}
}
}

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


_ Trường hợp lấy thông tin phía kết nối sau khi tiếp nhận kết nối: int getpeername (SOCKET s,
struct sockAddr* addr, int* addrlen);

_ Ví dụ:
// accept a connection
clientS = accept(s, NULL, NULL);
if (clientS == INVALID_SOCKET)
{
wsprintf(lpszMessage, “accept() generated error %d”,
WSAGetLastError());
MessageBox(lpszMessage, “Info”);
}
else
{
if (getpeername(clientS,
(LPSOCKADDR)&clientAddr, &nClientAddrLen)) == SOCKET_ERROR)
{
wsprintf(lpszMessage, “getpeername() generated error %d”,
WSAGetLastError());
MessageBox(lpszMessage, “Info”);
}
else
{
// copy the four byte IP address into an IP address
structure
memcpy(&clientIn, &clientAddr.sin_addr.s_addr, 4);
// print an informational message
wsprintf(lpszMessage,
“client IP address is %s, port is %d”,
inet_ntoa(clientIn), ntohs(clientAddr.sin_port));
MessageBox(lpszMessage, “Info”);
//...
}
}

f) Kết nối
_ Cú pháp: int connect

(SOCKET

s,

const

struct

sockAddr

FAR*

addr,

int

addrlen);

_ Thông số:
• s: handle của socket thực hiện kết nối.
• addr: địa chỉ cấu trúc dùng để chứa thông tin socket phía chờ kết nối.
• addrlen: địa chỉ biến chứa kích thước cấu trúc bởi addr.
_ Kết quả trả về: Thất bại: SOCKET_ERROR.
_ Ví dụ:
bool ConnectToServer (const Cstring &sServerAddress, short nServerPort)
{
bool bSuccess = true;
m_hSocket = socket (AP_INET, SOCK_STREAM, 0);
if (m_hSocket == INVALID_SOCKET) bSuccess = false;
else
{
SOCKADD_IN sockAddr;
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(nServerPort);
addrServer.sin_addr.s_addr = inet_addr(sServerAddress);
if (connect(s, (LPSOCKADDR) &addrServer, sizeof(addrServer))
== SOCKET_ERROR)
{
bSuccess = false;
closesock(m_hSocket);

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


}
return bSuccess;
}
}

g) Gửi nhận
_ Có thiết lập cầu nối:
• Cú pháp:
int send (SOCKET s, const char FAR* buf, int len, int flags);
int recv (SOCKET s, const char FAR* buf, int len, int flags);

• Thông số:
 s: handle của socket bên gửi.
 buf: địa chỉ vùng đệm chứa dữ liệu cần gửi.
 len: kích thước dữ liệu gửi (tính theo byte).
 flags: 0, MSG_DONTROUTR, MSG, OOB.
• Kết quả trả về:
 Thành công: số byte dữ liệu đã gửi.
 Thất bại: SOCKET_ERROR.
• Ví dụ:
 Gửi:
SOCKET s; // socket to communicate over
char pszBuf[100]; // buffer to send
int nBufLen; // number of bytes in buffer to send
int nBytesSent; // bytes sent
int nError; // error status
// create, bind, and connect socket s ...
lstrcpy(pszBuf, “Hello, World!”);
nBufLen = lstrlen(pszBuf);
nBytesSent = send(s, pszBuf, nBufLen, 0);
if (nBytesSent == SOCKET_ERROR) r = WSAGetLastError();
else { //... }

 Nhận:
SOCKET s; // socket to communicate over
#define BUFSIZE (100) // receive buffer size
char pszBuf[BUFSIZE]; // buffer to receive data
int nBytesRecv; // number of bytes received
int nError; // error status
// create, bind, and connect socket s ...
nBytesRecv = recv(s, pszBuf, BUFSIZE, 0);
if (nBytesRecv == SOCKET_ERROR) nError = WSAGetLastError();
else { //... }

_ Không thiết lập cầu nối:
• Cú pháp:
int sendto (SOCKET s, const char * buf, int size, int flags, const
struct sockAddr FAR* addrTo);
int recvfrom (SOCKET s, char* buf, int size, int flags, struct
sockAddr FAR* addrFrom);

• Thông số:
 s: handle của socket bên gửi.
 buf: địa chỉ vùng đệm chứa dữ liệu cần gửi.
 len: kích thước dữ liệu gửi (tính theo byte).
 flags: 0, MSG_DONTROUTR, MSG, OOB.
• Kết quả trả về:
 Thành công: số byte dữ liệu đã gửi.
 Thất bại: SOCKET_ERROR.
• Ví dụ:
 Gửi:
SOCKET s;

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


SOCKADDR_IN addr;
#define BUFSIZE (100)
char pszBuf[BUFSIZE];
int nBufLen;
int nBytesSent;
int nError;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
{
nError = WSAGetLastError();
// ...
}
else
{
// fill out the address of the recipient
addr.sin_family = AF_INET;
addr.sin_port = htons(2050);
addr.sin_addr.s_addr = inet_addr(“166.78.16.150”);
// assign some data to send
lstrcpy(pszBuf, “Hello, World!”);
nBufLen = lstrlen(pszBuf);
// send the datagram
nBytesSent
=
sendto(s,
pszBuf,
nBufLen,
(LPSOCKADDR)&addr, sizeof(addr));
if (nBytesSent == SOCKET_ERROR) { //... }
else { //... }
closesocket(s);
}

0,

 Nhận:
char pszMessage[100]; // informational message
SOCKET s; // socket to receive data on
SOCKADDR_IN addr; // address of the socket
#define BUFSIZE (100) // receive buffer size
char pszBuf[BUFSIZE]; // receive buffer
int nBytesRecv; // number of bytes received
int nError; // error code
SOCKADDR_IN addrFrom; // address of sender
int nAddrFromLen = sizeof(addrFrom); // lengh of sender
structure
IN_ADDR inFrom; // IP address of sender
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
{
nError = WSAGetLastError();
// ...
}
else
{
// fill out the name this server will read data from
addr.sin_family = AF_INET;
addr.sin_port = htons(2050);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// bind the name to the socket
if
(bind(s,
(LPSOCKADDR)&addr,
sizeof(addr))
==
SOCKET_ERROR)
{
nError = WSAGetLastError();
// ...
}
else

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


{
nBytesRecv = recvfrom(s, pszBuf, 100, 0,
(LPSOCKADDR)&addrFrom, &nAddrFromLen);
if (nBytesRecv == SOCKET_ERROR)
{
nError = WSAGetLastError();
// ...
}
else
{
// got some data ...
// copy the four byte IP address into an IP
address structure
memcpy(&inFrom,
&addrFrom.sin_addr.s_addr,
4);
// print an informational message
wsprintf(pszMessage,
“server received %d bytes from %s, port is
%d”,
nBytesRecv,
inet_ntoa(inFrom),
ntohs(addrFrom.sin_port));
}
closesocket(s);
}
}

3. Hai chế độ hoạt động của socket
a) Blocking
_ Các hàm thực hiện hoạt động nhập / xuất trên socket chỉ trả về khi tác vụ hoàn tất → Tiến trình bị chặn
nếu tác vụ chưa hoàn tất (sự kiện mong đợi chưa xảy ra).

b) Non-blocking
_ Các hàm thực hiện hoạt động nhập / xuất trên socket trở vền gay sau khi được gởi.
_ Phát sinh lỗi WSAEWOULDBLOCK nếu tác vụ yêu cầu chưa hoàn tất → Tiến trình không bị chặn.

4. Mô hình xử lý
a) Blocking
_ Sử dụng các hàm socket theo chế độ hoạt động mặc định (blocking).
_ Thường sử dụng giải pháp xử lý đa luồng (multithread).

b) WSAAsyncSelect
_ Mô hình xử lý bất đồng bộ:
• Ứng dụng đăng ký sự kiện mong đợi xảy ra trên socket.
• Hệ thống giám sát và gửi thông điệp báo hiệu đến ứng dụng khi sự kiện xảy ra.
• Ứng dụng xử lý khi nhận được thông điệp.
_ Giải pháp phù hợp với mô hình hoạt động hướng thông điệp của Windows.
_ Chọn chế độ xử lý bất đồng bộ:
int WSAAsyncSelect (SOCKET s, HWND hWnd, UINT message, long IEvent),

trong đó sự kiện mong đợi (IEvent) bao gồm:
• FD_ACCEPT, FD_CONNECT.
• FD_READ, FD_WRITE.
• FD_CLOSE.
• FD_OOB.
_ Đăng ký nhiều sự kiện:
• Đúng:
WSAAsyncSelect (s, hWnd, USER_MESSAGE, FD_READ | FD_CLOSE);

• Sai: Thông điệp báo hiệu do người lập trình định nghĩa
#define (WM_USERtn)
const UINT = WM_USERtn;

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


c) Tạo trình xử lý thông điệp (MFC)
_ Hàm thành phần của lớp cửa sổ nhận thông điệp:
• Khai báo:
LRESULT (WPARAM wParam, LPARAM lParam);

trong đó:
 wParam: handle socket xảy ra sự kiện mong đợi.
 lParam: mã sự kiện xảy ra và lỗi sai.
• Định nghĩa:
LRESULT ::(WPARAM wParam, LPARAM lParam)
{
if (WSAGETSELECTERROR (lParam == 0)
{
switch (WSAGETSELECTEVENT (lParam))
{
case FD_ACCEPT: //...; break;
case FD_READ: //...; break;
case FD_CLOSE: //...; break;
//...
}
}
else { //... }
return LRESULT();
}

• Ví dụ:
const UINT MSG_ASYNC = WM_USER + 1;
bool ::ConnectToServer (const Cstring &sIpAddr, short
nServerPort)
{
bool bSuccess = true;
m_hSocket = ...;
if (m_hSocket != INVALID_SOCKET)
{
SOCKADD_IN sockAddr;
if (connect (m_hSocket, ..., ... ) == SOCKET_ERROR ||
WSAAsynSelect (m_hSocket, m_h Wnd, MSG_ASYNC, FD_READ |
FD_CLOSE) == SOCKET_ERROR)
{
closesocket (m_hSocket);
bSuccess = false;
}
}
else bSuccess = false;
return bSuccess;
}
LRESULT ::(WPARAM wParam, LPARAM lParam)
{
if (WSAGETSELECTERROR (lParam) == 0)
{
switch (WSAGETSELECTEVENT)
{
case FD_READ: ReceiveData(); break;
case FD_CLOSE: closesocket (m_hSocket); break;
}
}
else { //... }
return 0L;
}

_ Đăng ký trình xử lý:

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


BEGIN_MESSAGE_MAP(, )
//...
ON_MESSAGE (, )
END_MESSAGE_MAP

trong đó:
• MSG_ASYNC: thông điệm do người lập trình định nghĩa.
• OnAsyncSelect tên trình xử lý thông điệp.

VII. Ứng dụng MiniChat
1. Mô tả
_ Hai thành phần:
• Server:
 Quản lý người dùng theo nhóm.
 Tổ chức đăng nhập theo nhóm.
 Tổ chức trao đổi trong nhóm.
• Client:
 Giao tiếp với người dùng.
 Cho phép đăng nhập theo nhóm.
 Cho phép “trò chuyện” trong nhóm.
_ Giao thức ứng dụng:
• Server port: 2013: có thiết lập cầu nối.
• Tập lệnh (Client  Server):
 GLIST: yêu cầu danh sách nhóm :
LOGIN ,

 ULIST: yêu cầu danh sách người dùng trong nhóm:
 Gửi nội dung trò chuyện:
TALKS

 LGOUT: đăng xuất.
 Ký hiệu đặc biệt để ngăn cắt: CRLF.
• Dạng hồi đáp (Server  Client):
 Khi thiết lập cầu nối: xuất lời chào.
 Khi nhận các lệnh:


trong đó:
: 0 là thành công, 1 là thất bại.
:
 Lệnh GLIST (trường hợp thành công):
message = , …,

 Lệnh ULIST (trường hợp thành công):
message = , …,

 Lệnh LOGIN, LGOUT, TALKS (hoặc trường hợp thất bại):
message =

2. Client
a) Giao diện
_ Hộp thoại chính.
_ Hộp thoại phụ trợ.

b) Trạng thái hoạt động

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


c) Cài đặt
_ Ứng dụng dạng hộp thoại.
_ Lớp hộp thoại ứng dụng:
• Dữ liệu:
 socket handle: SOCKET m_hSocket.
 Trạng thái hiện tại:
enum FSTATE {FS_BEGIN, FS_CONNECT,
FS_ULIST, FS_TALKS, FS_LOGOUT};
FSTATE m_fState
 Tên đăng nhập: Cstring m_sUserName

FS_GLIST,

FS_LOGIN,

 Thành phần liên kết với điều khiển:
CString m_sMessage
CListBox m_lbGroups
CListBox m_lbUsers
CListBox m_lbContent

• Thao tác:
 Trình xử lý sự kiện:
 Tác động trên các nút:
 Kết nối (Connect):
 Kiểm tra trạng thái chưa kết nối.
 Mở hộp thoại kết nối (Connect Dialog).
 Thực hiện kết nối – gọi thao tác phụ trợ (ConnectToServer).
 Đặt trạng thái: đang kết nối.
 Hoạt động bất đồng bộ:
 Lấy Danh sách Nhóm (Get Groups):
 Kiểm tra trạng thái kết nối.
 Gởi lệnh GLIST.
 Đặt trạng thái: đang lấy danh sách nhóm.
 Đăng nhập (Login):
 Kiểm tra trạng thái đã kết nối và chưa đăng nhập.
 Mở hộp thoại đăng nhập (Login Dialog).
 Gởi lệnh LOGIN.
 Đặt trạng thái: đang đăng nhập.
 Lấy Danh sách Người dùng (Get Users):
 Kiểm tra trạng thái đã đăng nhập.
 Gởi lệnh ULIST.
 Đặt trạng thái: đang lấy danh sách người dùng.
 Gửi (Send):
 Kiểm tra trạng thái đã đăng nhập.
 Gởi lệnh TALKS.
 Đặt trạng thái: đang trao đổi.
 Đăng xuất (Logout):
 Kiểm tra trạng thái đã đăng nhập.
 Gởi lệnh LGOUT.
 Đặt trạng thái: đang thoát ra khỏi nhóm.
 Hoạt động bất đồng bộ:
 Kiểm tra mã báo lỗi.
 Thực hiện / gọi tác vụ xử lý sự kiện tương ứng:
 FD_CONNECT: báo kết nối thành công.
 FD_READ: nhận và xử lý hồi đáp từ server.
 FD_CLOSE: đóng socket  mfState = FS_BEGIN  Thông báo
đã đóng kết nối
 Xử lý hồi đáp:
 Kết nối (Connect):
 Hiển thị lời chào nhận từ server.

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


 Đặt trạng thái: đã kết nối.
 Lấy Danh sách Nhóm (Get Groups):
 Kiểm tra mã hồi đáp: nếu thành công thì hiển thị danh sách nhóm
 tách các tên nhóm và đưa vào listbox; nếu thất bại thì hiển thị
thông điệp báo lỗi nhận từ server.
 Hiển thị thông báo nhận từ server.
 Đăng nhập (Login):
 Kiểm tra mã hồi đáp: nếu thành công thì đặt trạng thái đã đăng
nhập (sẵn sàng đón nhận thông điệp); nếu thất bại thì đặt trạng thái:
đã kết nối (chưa đăng nhập).
 Hiển thị thông báo nhận từ server.
 Lấy Danh sách Người dùng (Get Users):
 Kiểm tra mã hồi đáp: nếu thành công thì hiển thị danh sách người
dùng; nếu thất bại thì hiển thị thông điệp báo lỗi nhận từ server.
 Đặt trạng thái: sẵn sàng nhận thông điệp.
 Gửi (Send):
 Kiểm tra mã hồi đáp: Thành công: đặt trạng thái: đã kết nối (chưa
đăng nhập).
 Hiển thị thông báo nhận từ server.
 Thao tác phụ trợ:
 Tạo cầu nối đến server (ConnectToServer):
 Thông số: [vào] Địa chỉ server (dạng chuỗi), [vào] số hiệu cổng.
 Kết quả trả về: nếu thành công là true; nếu thất bại là false.
 Thực hiện: Kết nối (hoạt động theo chế độ blocking), chọn chế độ
hoạt động bất đồng bộ: FD_READ | FD_CLOSE.
 Nhận dữ liệu (ReceiveData):
 Xử lý nhận dữ liệu: nội dung hồi đáp từ server.
 Gọi thao tác xử lý hồi đáp tương ứng, tùy thuộc trạng thái hiện tại
của client.
 Gởi dữ liệu (SendData).

3. Server
a) Giao diện
_ Hộp thoại chính.
_ Hộp thoại phụ trợ.

b) Cài đặt
_ Ứng dụng dạng hộp thoại.
_ Các lớp phụ trợ:
• CUserSocket:
 Kế thừa từ CObject.
 Dữ liệu:
 socket handle: SOCKET m_hSocket.
 Tên đăng nhập: CString m_sName.
 Địa chỉ, cổng phía kết nối:
int m_nPeerPort.
CString m_sPeerAddress.

 Thao tác:
 Truy xuất thông tin.
 Cập nhật thông tin.
• CUserGroup:
 Kế thừa từ CObject.
 Dữ liệu:
 Tên nhóm: CString m_sName.
 Danh sách các usersocket:
CTypedPtrList m_userList.

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


 Thao tác:
 Thêm người dùng.
 Lấy người dùng ra khỏi nhóm.
 Tìm người dùng.
 Truy xuất tên nhóm.
 Lấy danh sách tên nhóm.
• CGroupList:
 Dữ liệu: Danh sách các nhóm:
CArray m_groupList.

 Thao tác:
 Tìm nhóm.
 Theo tên nhóm.
 Theo socket handle.
 Tìm nhóm và người dùng: theo socket handle.
 Lấy danh sách tên nhóm.
_ Lớp hộp thoại ứng dụng:
• Dữ liệu:
 socket handle – “lắng nghe”.
 Danh sách nhóm: CGroupList m_groupList.
 Danh sách người dùng mới kết nối: CUserList m_groupNewUsers.
 Thành phần liên kết với các điều khiển.
• Thao tác:
 Khởi tạo:
 Thông số: port lắng nghe.
 Kết quả trả về: nếu thành công là socket handle; nếu thất bại là
INVALID_SOCKET.
 Dữ liệu nhóm: gồm tập tin dữ liệu hoặc cơ sở dữ liệu.
 Socket “lắng nghe” – InitListenSocket:
Socket()
Bind()
Listen()
WSAAsyncSelect() - FD_ACCEPT

 Trình xử lý sự kiện:
 Tác động trên phần tử giao diện:
ListBox: Nhóm.
Button: Xóa, ẩn.
 Hoạt động bất đồng bộ.
 Xử lý đáp ứng yêu cầu từ client:
 GLIST:
 Tạo nội dung hồi đáp theo quy định: sử dụng thao tác lấy danh sách tên
nhóm của CGroupList.
 Gởi hồi đáp.
 LOGIN:
 Kiểm tra người dùng chưa đăng nhập.
Kiểm tra thông tin đăng nhập:
 Tên nhóm có thật:
 Tên người dùng không trùng lắp.
 Chuyển người dùng sang nhóm đăng nhập (trường hợp thành công):
 Xóa khỏi danh sách người dùng mới kết nối.
 Thêm vào danh sách người dùng của nhóm đăng nhập.
 Cập nhật tên đăng nhập.
 Tạo hồi đáp theo quy định gửi hồi đáp.
 ULIST:
 Kiểm tra là người dùng đã đăng nhập (hiện diện trong danh sách của một
nhóm).

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


 Tạo nội dung hồi đáp theo quy định (sử dụng thao tác lấy danh sách tên
người dùng của CUserGroup).
 Gửi hồi đáp.
 LGOUT:
 Kiểm tra là người dùng đã đăng nhập (hiện diện trong danh sách của một
nhóm).
 Chuyển người dùng sang danh sách mới kết nối (trường hợp thành
công).
 Xóa khỏi danh sách người dùng mới của nhóm.
 Thêm vào danh sách người dùng mới kết nối.
 Tạo hồi đáp theo quy định.
 Gửi hồi đáp.
 “Broadcast”:
 Kiểm tra là người dùng đã đăng nhập (hiện diện trong danh sách của một
nhóm).
 Sử dụng thao tác tìm nhóm và người dùng theo socket handle của lớp
CGroupList.
 Tạo thông điệp “broadcast” (tên người dùng gửi + “:” + nội dung trò
chuyện).
 Gửi thông điệp “broadcast” cho các người dùng còn lại trong nhóm.
 Thao tác phụ trợ:
 Tiếp nhận kết nối (AcceptConnection):
 Nhận dữ liệu (ReceiveData).
 Phân tích yêu cầu (ParseRequest):
 Xác định mã lệnh, gọi tác vụ.
 Xừ lý đáp ứng yêu cầu.
 Gửi dữ liệu (SendData).

4. Minh họa
_ Thiết lập kết nối:
bool CChatClDlg::ConnectToServer (const CString &sServerAddress, short
nServerPort)
{
bSuccess = true;
m_hSocket = socket (…, …, 0);
if (m_hSocket != INVALID_SOCKET)
{
SOCKETADD_IN sockAddr;
sockAddr.sin_family = …
sockAddr.sin_port = htons (nServerPort);
if (isalpha (sServerAddress[0])
{
PHOSTENT pHost = gethostbyname (sServerAddress);
if (pHost) memcpy (&sockAddr.sin_addr, pHost->h_addr, 4);
}
else sockAddr.sin_addr = inet_addr (sServerAddress);
if
(connect
(m_hSocket,
(LPSOCKADDR)
&
sockAddr,
sizeof(sockAddr)) == SOCKET_ERROR || WSAAsyncSelect, FDREAD
| FDCLOSE) == SOCKET_ERROR)
{
closesocket (m_hSocket);
bSuccess = false;
}
else bSuccess = false;
return bSuccess;
}
}

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


void CChatClDlg::OnBnClickedConnect()
{
if (m_fState < FSCONNECT) // chưa kết nối
{
ConnectDlg dlg; // hộp thoại để nhập thông tin server
if (dlg_DoModal() == IDOK)
{
if
(ConnectToServer
(dlg.m_nServerAddress)
dlg.m_nServerPort)
{
mlbContent.AddString (_T(“Đã kết nối”));
m_fState = FS_CONNECT;
}
else mlbContent.AddString (_T(“Kết nối thất bại”));
}
}
}

==

_ Trình xử lý cho hoạt động xử lý bất đồng bộ:
• Hàm thành phần của C…Dlg (lớp hộp thoại chính của ứng dụng).
LRESULT C…Dlg::OnAsyncSelect (WPARAM wParam, LPARAM lParam)
{
if (WSAGETSELECTERROR (lParam) == 0)
{
switch (WSAGETSELECT (lParam))
{
case FD_READ: ReceiveData(); break;
case FD_CLOSE:
closesocket (m_hSocket);
m_fState = FS_BEGIN;
m_lbContent.AddString(_T(“...”);
break;
}
}
else { //…}
return LRESULT(0);
}

• Đăng ký trình xử lý:
BEGIN_MESSAGE_MAP (C…Dlg:Cdialog)
...
ON_MESSAGE (MSG_ASYNC, OnAsyncSelect); // tự định nghĩa
END_MESSAGE_MAP
const UNIT MSG_ASYNC = WM_USER + 1;

• Hàm thành phần thực hiện nhận dữ liệu:
const int BUF_LEN = 255;
void C…Dlg::ReceiveData()
{
char szBuffer[BUF_LEN + 1];
int nRecvBytes = recv (m_hSocket, szBuffer, BUF_LEN , 0);
if (nRecvBytes > 0)
{
szBuffer[nRecvBytes] = ‘\0’;
switch (m_fState):
{
case FS_CONNECT: m_lbContent.AddString (szBuffer);
break;
case
FS_GLIST:
ProcessGListReply(nRecvBytes);
break;
}
}

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


}
void C…Dlg::SendData(const CString &sData)
{
return send(m_hSocket, sData, sData.GetLength
SOCKET_ERROR);
}

(),

0)

!=

_ Xử lý yêu cầu lấy danh sách nhóm:
• Gởi yêu cầu (lệnh GLIST): khi người dùng nhấn nút GetGroup  Cài đặt trình xử lý sự kiện
nhấn nút GetGroup.
• Xử lý hồi đáp: khi có nhận dữ liệu từ server và client đang ở trạng thái “yêu cầu danh sách
nhóm” (FS_GLIST).
• Khi nhấn nút GetGroup:
void C…Dlg::OnBnClickedGetGroup()
{
if (m_fState >= FS_CONNECT) //đã kết nối
{
m_fState = FS_GLIST;
}
}

• Hàm thành phần xử lý hồi đáp cho yêu cầu lấy danh sách nhóm:
void C…Dlg::ProcessGListReply (const CString &sReply)
{
if (sReply[0] == “MaHoiDap”)
{
int end, begin = HEADER_LEN // tự định nghĩa
m_lbGroups.ResetContent();
while ((end = sReply.Find (‘,’, begin)) >= 0)
{
m_lbGroups.AddString (sReply.Mid (begin, end – begin));
begin = end + 1;
}
m_lbGroups.AddString (sReply.Mid(begin));
}
else
}

_ Xử lý đăng nhập:
• Xử lý gởi yêu cầu (lệnh LOGIN): cần 2 thông số là tên nhóm và tên người dùng.
void C...Dlg::OnBnClickedLogin()
{
if (m_fState >= FS_CONNECT && m_fState < FS_LOGIN)
{
CLoginDlg dlg;
int index = m_lbGroups.GetCurSel();
if (index != LB_ERR)
m_lbGroups.GetText (index, dlg.m_sGroupsName) ;
if (dlg.DoModal() == IDOK)
{
if
(dlg.m_sGroupName.IsEmpty()
||
dlg.m_sUserName.IsEmpty())
MessageBox(_T(“Thiếu thông tni”), _T(“Lỗi”),
MB_OK | MB_ICON ERROR)
else
{
CString sLogin Cmd;
sLoginCmd.Format
(_T(“LOGIN
%S,
%S”),
dlg.m_GroupName, dlg.m_sUserName);
if (SendData (sLoginCmd))
{

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


m_fState = FS_LOGIN;
m_UserName = dlg.m_UserName;
}
}
}
}
}

• Xử lý hồi đáp.
void C…Dlg::ProcessLoginReply (const CString &sReply)
{
if (sReply[0] == ‘0’)
m_fState = ...;// sẵn sàng nhận nội dung trò chuyện
trong nhóm
else
{
m_lbContent.AddString (sReply.Mid(HEADER_LEN));
m_fState = FS_CONNECT;
}
}

_ Xử lý yêu cầu lấy danh sách người dùng:
• Xử lý gởi yêu cầu (lệnh ULIST): tương tự trường hợp yêu cầu danh sách nhóm nhưng
m_fState >= FS_LOGIN.
• Xử lý hồi đáp: tương tự trường hợp xử lý hồi đáp cho yêu cầu danh sách nhóm:
 Hiển thị danh sách trên listbox m_lbUsers.
 m_fState = ...;// sẵn sàng nhận nội dung trò chuyện.
_ Xử lý yêu cầu trò chuyện:
• Xử lý gởi yêu cầu (lệnh TALKS): có một thông số là nội dung trò chuyện.
• Xử lý hồi đáp: hiển thị nội dung trò chuyện.
void C…Dlg::OnBnClickedSend()
{
if (m_fState >= FS_LOGIN)
{
UpdataData(true);
if (SendData (_T(“TALKS “) + m_sMessage))
{
m_lbContent.AddString (m_sUserName + _T(“: “) +
m_sMessage);
m_fState = FS_TALKS;
m_sMessage.Empty();
UpdataData(false);
}
}
}

_ Xử lý yêu cầu đăng xuất:
• Xử lý gởi yêu cầu (lệnh LOGOUT):
void C…Dlg::OnBnClickedLogout()
{
if (m_fState >= FS_LOGIN)
{
UpdataData(true);
if (SendData (_T(“LGOUT“)) m_fState = FS_LOGOUT;
}
}

• Xử lý hồi đáp:
void C…Dlg::ProcessLooutReply ()
{
if (sReply[0] == ‘0’) m_fState = FS_CONNECT;
m_lbContent.AddString (sReply.Mid(HEADER_LEN));

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


}

_ Xử lý khi người dùng đóng ứng dụng:
• Đóng socket.
• Trình xử lý thông điệp: .WM_CLOSE.
void C…Dlg::OnClose()
{
if (m_fState > FS_BEGIN) closesocket (m_hSocket);
}

VIII. Thư viện lớp MFC
1. Giới thiệu
_ MFC:
• Microsoft Foundation Class Library.
• Application Framework.
_ MFC Socket Classes:
• CAsyncSocket
• CSocket.
•…

2. Lớp CASynSocket
_ Đặc tả khái niệm socket.
_ Kế thừa từ CObject:
• Cung cấp giao diện lập trình mạng: Giao diện lập trình mạng mức thấp (che giấu chi tiết sử
dụng Windows API):
 Các hàm thành phần: tương ứng với các hàm Winsock API.
 Các hàm callback: được tự động gọi khi có sự kiện xảy ra với socket.
 Người lập trình tự giải quyết các vấn đề:
 Hoạt động blocking.
 Sự khác biệt: Trật tự byte và mã ký tự.
• Thành phần:
 Dữ liệu: SOCKET m_hSocket.
 Tác vụ:
 Tạo lập:
 CASyncSocket(…).
 Create(…).
 Truy xuất thông tin:
 GetSockName(…).
 GetSockNameEx(…) (cho IPv6).
 Tạo, đóng socket:
 Socket(…).
 Close(…).
 Thiết lập cầu nối:
 Bind(…).
 Listen(…).
 Accept(…).
 Connect(…).
 Gởi nhận dữ liệu:
 Send(…).
 Receive(…).
 SendTo(…).
 ReceiveFrom(…).
 SendToEx(…).
 ReceiveFromEx(…).
 Khác:
 Attach(…).
 Detach(…).

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


 Callback:
 OnAccept(…): FD_ACCEPT.
 OnConnect(…): FD_CONNECT.
 OnSend(…): FD_WRITE.
 OnReceive(…): FD_READ.
 Chi tiết sử dụng:
 Tạo đối tượng socket:
 Quá trình hai bước:
 Thiết lập.
 Gọi hàm Create:
bool Create
(
UINT nSocketPort = 0;
int nSocketType = SOCK_STREAM,
long lEvent = FD_READ | FD_WRITE | FD_OOB
| FD|ACCEPT | FD_CONNECT | FD_CLOSE
LPCTSTR lpszSocketAddress = NULL
);

 Minh họa:
 Cấp phát tĩnh:
CasyncSocket sock;
Sock.Create(…);

 Cấp phát động:
CAsyncSocket *pSock = new CAsyncSocket;
pSocke->Create(…);

 Thiết lập cầu nối:
 Lắng nghe:
bool Listen (int nConnectionBacklog = 5);
sock.Listen(…);
pSock->Listen(…);
 Tiếp nhận: Không gọi hàm Create cho đối tượng rConnectedSocket:
CAsyncSocket connectedSocket;
sock.Accept (connectedSocket, ...);
CAsyncSocket *pConnectedSocket = new CAsyncSocket;
pSock->Accept (**pConnectedSocket, ...);

 Kết nối:
bool

Connect

(LPCTSTR

lpszHostAddress,

UINT

nHostPort);
bool

Connect

(const

SOCKADDR*

lpSockAddr,

int

nSockAddrLen);
sock.Connect (“127.0.0.1”, 2012);
pSock->Connect (“127.0.0.1”, 2012);

 Gởi nhận dữ liệu:
 Có cầu nối:
virtual int Send (const void *lpBuf, int nBufLen,
int nFlags = 0);
virtual int Receive (void *lpBuf, int nBufLen, int
nFlags = 0);

 Không cầu nối.
 Hủy đối tượng socket:
 Cấp phát tĩnh: tự hủy khi thực thi khỏi tầm vực khai báo.
 Cấp phát động: delete pSock.
 Phương thức hủy tự động gọi thao tác Close.
 Xử lý sự kiện xảy ra với socket:
 Định nghĩa lại thao tác xử lý cho các hàm callback.
virtual void OnAccept (int nErrorCode);
virtual void OnClose (int nErrorCode);

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


virtual
virtual
virtual
virtual

void
void
void
void

OnConnect (int nErrorCode);
OnReceive (int nErrorCode);
OnSend (int nErrorCode);
OnOutOfBandDate (int nErrorCode);

 Các hàm callback được tự động gọi khi có sự kiện xảy ra với socket.

3. CSocket
a) Khái quát
_ Kế từ từ lớp CasyncSocket: mức trừu tượng cao.
_ Trừu tượng hóa họat động gửi nhận dữ liệu:
• CsocketFile.
• CArchive.
_ Chế độ hoạt động: blocking (phù hợp với CArchive).

b) Thành phần
_ Tạo đối tượng:
CSocket();
bool Create
{
UNIT nSocketPort = 0;
int nSocketyType = SOCK_STREAM;
LPCTSTR lpszSocketAddress = NULL;
}

_ Liên quan đến blocking mode:
bool IsBlocking();
void CancelBlockingCall();
virtual bool OnMessagPending();
static CSocket * PASCAL FromHandle (SOCKET hSocket);

c) Chi tiết sử dụng
_ Tạo đối tượng socket.
_ Thiết lập cầu nối:
• Server:
 Socket.Listen();
 Sock.Accept(…);
 pSock->Listen();
 pSock->Accept(…);
• Client:
 sock.Connect(…);
 pSock->Connect(…);
_ Gửi nhận dữ liệu:
• Tạo đối tượng CSocketFile (liên kết với đối tượng CSocketFile):
CSocketFile sockFile (&sock,
CSocketFile sockFile (psock,
• Để nhận: CArchive arIn (&sockFile,
• Để gởi: CArchive arOut (&sockFile,

…);
…);
CArchive::load, ...);
CArchive::store, ...);

• CArchive không làm việc với Datagram Socket.
_ Kết thúc: Hủy đối tượng CArchive, CSocketFile, CSocket.

4. Vấn đề thiết kế
a) Xây dựng lớp socket
_ Kế thừa từ CAsyncSelect, CSocket.
_ Bổ sung thành phần mới.
_ Định nghĩa lại các thao tác:
CAsyncSelect::OnReceive(...).
CAsyncSelect::OnSend(...).
CAsyncSelect::OnAccept(...).
CAsyncSelect::OnClose(...).
...
CSocket::OnMessagePeding(...).

CuuDuongThanCong.com

https://fb.com/tailieudientucntt


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×