THIẾT KẾ VÀ HIỆN THỰC CHƯƠNG TRÌNH QUẢN LÝ QUẢNG CÁO TRÊN TRANG WEB.
Trang 1TRƯỜNG ĐẠI HỌC KỸ THUẬT KHOA CÔNG NGHỆ THÔNG TIN
TRÊN TRANG WEB
Giáo viên hướng dẫn : Ts NGUYỄN VĂN HIỆP
Sinh viên thực hiện : VŨ NGỌC PHAN
Khoá : 1995 – 2000
Trang 2Lời cảm ơn
Xin chân thành cám ơn :
- Thầy Nguyễn Văn Hiệp – giảng viên Khoa Công Nghệ Thông Tin trường Đại Học Kỹ Thuật Tp Hồ Chí Minh đã tận tình hướng dẫn
em hoàn thành luận văn này.
Trân trọng gởi lời cám ơn đến :
- Ban Giám Hiệu, các thầy cô trường Đại Học Kỹ Thuật Tp Hồ Chí Minh
- Ban chủ nhiệm và các thầy cô trong Khoa Công Nghệ Thông Tin
Đã tận tình dạy chỗ em trong suốt thời gian học tập tại trường.
Và tôi cũng xin gởi lời cám ơn đến các bạn cùng khoá đã nhiệt tình giúp đỡ tôi trong thời gian qua.
Trang 3NỘI DUNG
Lời cảm ơn
Nội dung
Lời nói đầu
Phần mở đầu 1
I Phương hướng tiếp cận đề tài 2
II Mục đích của đề tài 3
III Yêu cầu của đề tài 3
Phần 1 : CƠ SỞ LÝ THUYẾT CHƯƠNG 1: KHÁI NIỆM CƠ BẢN 4
I Mô hình ứng dụng client - server và ứng dụng trên Web 4
II Ưùng dụng trên Web 7
III CGI và ISAPI 8
1 CGI 8
2 ISAPI 13
IV So sánh và đánh giá 17
1 Hoạt động của ứng dụng CGI 17
2 CGI, ISAPI và WINCGI 17
3 Overhead của ISAPI 19
4 tạo ứng dụng Internet Server bằng ISAPI 19
CHƯƠNG 2 : ISAPI EXTENSIONS 20
I DLL trong ISAPI Extensions 20
II MFC cho ISAPI Extensions 24
1 CHttpServer 24
2 CHttpServerContext 24
3 CHtmlStream 25
4 Form và Parse Map 25
III Sử dụng ISAPI Extension để truy xuất database 29
1 ODBC và DAO 29
2 Sử dụng MFC để truy xuất database 29
3 ISAPI trong việc truy xuất database 31
CHƯƠNG 3 : CHUẨN ODBC - INTERNET INFORMATION SERVER 34
I ODBC 34
II Internet Information Server 36
1 Web server 36
2 IIS 36
CHƯƠNG 4: NHỮNG KHÁI NIỆM VỀ QUẢNG CÁO TRÊN WEB 40
Trang 4I Một số định nghĩa 40
II Chiến lược quảng cáo 42
1 Dạng file của Ad banner 42
2 Alt Text 42
3 Đưa ad banner ra trang web 43
4 Sắp xếp Ad banner 43
PHẦN 2 : HIỆN THỰC CHƯƠNG TRÌNH CHƯƠNG 1 : PHÂN TÍCH CHƯƠNG TRÌNH 46
I Phân tích chương trình 46
1 Advertiser 47
2 Campaign 47
3 Advertisement 48
II Mô tả chương trình 49
1 Phía Advertiser 49
2 Phía AdMaster 50
CHƯƠNG 2 :THIẾT KẾ CHƯƠNG TRÌNH 52
I Cơ sở dữ liệu 52
1 Tổ chức cơ sở dữ liệu 52
2 Các store procedure 59
II Giải thuật đưa banner quảng cáo ra trang Web 63
1 Giải thuật tạo số ngẫu nhiên 63
2 Giải thuật chọn ad banner trong nhóm 64
III Các thành phần chính của AdServer 66
1 Advertiser 66
2 AdMaster 66
3 Ad-Server 66
4 Quy trình thực hiện 68
Kết luận 92
Phụ lục 93
Tài liệu tham khảo 111
Trang 5Lời mở đầu
M
ột trong các hướng phát triển quan trọng hàng đầu của Công nghệ Thông Tin hiện nay là các công nghệ liên quan đến Internet Trong hướng này thì quan trọng hàng đầu lại là các hệ thống thương mại điện tử thực hiện trên Internet, trong đó chuyên mục quảng cáo và quản lý các chuyên mục này góp phần không nhỏ cho sự thành công của thương mại điện tử
Tất cả nhà sản xuất đều muốn sản phẩm của mình sản xuất ra được càng nhiều khách hàng biết đến và được bán ra với doanh thu cao nhất càng tốt Khi nền kinh tế thị trường phát triển, sản phẩm của nhà sản xuất phải cạnh tranh mãnh liệt thì việc quảng cáo càng chiếm phần quan trọng trong giai đoạn phân phối sản phẩm Họ có thể sử dụng các phương tiện truyền thông đại chúng như phát thanh, truyền hình, các biểu ngữ v.v… Đó là cách quảng cáo trong thời đại nông nghiệp và công nghiệp
Đến thời đại thông tin, công nghệ thông tin được nhúng ghép vào hầu hết các sản phẩm và dịch vụ kinh tế xã hội, làm tăng các giá trị hàng hoá và dịch vụ Cùng với mỗi thay đổi trong phương thức giao tiếp, cũng như nhu cầu gia tăng của số lượng người sử dụng Internet kèm theo việc mua sắm hàng hoá và dịch vụ qua Internet ngày càng nhiều nên các doanh nghiệp cảm nhận được áp lực phải hành động nhanh với những dịch vụ mới và một cơ sở hạ tầng hợp lý để có thể cạnh tranh trong thế giới này Việc thay đổi cách thức quảng cáo và quản lý quảng cáo nhằm phổ biến rộng rãi sản phẩm của doanh nghiệp mình là điều không thể thiếu Chẳng hạn trong việc phục vụ khách du lịch, Công nghệ Thông tin tham gia vào từ khâu đặt vé máy bay, đặt chỗ khách sạn đến các dịch vụ thông tin đi kèm
Qua những yêu cầu như trên mà em đã chọn đề tài cho Luận văn tốt nghiệp của mình là “THIẾT KẾ VÀ HIỆN THỰC CHƯƠNG TRÌNH QUẢN LÝ QUẢNG CÁO TRÊN TRANG WEB” Bước đầu nghiên cứu, hiện thực với kiến thức, khả năng và thời gian có hạn, luận văn này chắc chắn sẽ không tránh khỏi những thiếu sót, rất mong được quý thầy cô và các bạn góp ý để có thể hoàn chỉnh hơn trong quá trình nghiên cứu sau này
Tháng 1/2000SINH VIÊN THỰC HIỆN
Trang 6MỞ ĐẦU
Trang 7I Phương hướng tiếp cận đề tài :
Hệ thống quản lý quảng cáo trên Web được phát triển dựa trên mô hình Client/Server Giao tiếp giữa client và server thông qua CGI, là một chuẩn giao tiếp chung giữa browser và server
1 Các bước tiếp cận đề tài :
Ban đầu, khái niệm quảng cáo trên Web đối với em hết sức mơ hồ và xa lạ Để có khái niệm và biết cách thức hoạt động của các hệ thống quản lý quảng cáo trên Web, em đã tham khảo một số Web site hiện thực loại hình quảng cáo này như : DoubleClick, AdServer , tham khảo thành phần AdServer trong gói phần mềm Microsoft Site Server
Ngoài những đặc điểm tương tự như quảng cáo bằng các phương tiện thông thường như : báo chí, truyền hình Quảng cáo trên Web còn đem lại cho ta khả năng nắm bắt thông tin khách hàng tốt hơn, nhanh chóng và chính xác hơn Ngoài ra, chi phí bỏ ra cho quảng cáo trên Web lại rẻ hơn nhiều so với các loại quảng cáo khác
2 Nghiên cứu các công cụ lập trình trên Web :
- Để tạo trang Web hoàn chỉnh và liên kết chúng với nhau, ở đây ta sử dụng ngôn ngữ HTML, JavaScript, cũng như các liên kết và Method trong một form HTML
- Để thao tác với Cơ sở dữ liệu trên server từ Browser, ta sử dụng các CGI scripts giao tiếp với Database server thông qua lớp vỏ và các lệnh của nó
- Cơ sở dữ liệu trên server là một database Server (cụ thể là SQL Server phiên bản 7.0)
- Vì chương trình hiện thực trên môi Microsoft Windows nên sẽ được viết bằng Visual C++, sử dụng Wizard ISAPI Extension, một phương tiện tương đương với CGI nhưng chạy nhanh hơn CGI, chạy rất ổn định đối với lượng tải lớn và truy xuất
cơ sở dữ liệu khá nhanh
II Mục đích của đề tài :
Đề tài được thực hiện nhằm mục đích:
- Nghiên cứu và hệ thống hoá nguyên tắc, kỹ thuật tổ chức một chương trình quản lý quảng cáo trên Web
- Nghiên cứu cơ chế CGI và áp dụng cơ chế này vào đề tài thông qua chương trình trên
III Yêu cầu của đề tài:
Yêu đầu đặt ra đối với đề tài là :
Trang 8- Tổ chức cơ sở dữ liệu quảng cáo.
- Xây dựng giải thuật hiển thị banner quảng cáo ra trang Web dựa vào trọng số của banner
Banner quảng cáo được đưa ra trang Web dựa vào trọng số của chúng Trong tập hợp nhiều banner, banner nào có trọng số càng lớn thì khả năng xuất hiện của banner này trên trang Web càng lớn Giải thuật được xây dựng sao cho khả năng chọn lựa banner là tối ưu và hợp lý nhất
- Thống kê các thông tin liên quan đến banner quảng cáo
Trang 9CƠ SỞ LÝ THUYẾT
Trang 10_Chương 1
NHỮNG KHÁI NIỆM CƠ BẢN
I Mô hình ứng dụng Client - Server và ứng dụng trên Web
Client - Server là một mô hình tính toán khi máy client gởi một yêu cầu nào đó tới máy server Yêu cầu thường là để truy xuất thông tin như những yêu cầu trong database, hay yêu cầu để xử lý như cập nhật database hoặc chạy một số quá trình nào đó Máy client thực hiện yêu cầu, và máy server đáp ứng yêu cầu này Lợi ích của hệ thống client-server là tận dụng được sức mạnh của mỗi máy hoặc hệ điều hành Client thực hiện một số ứng dụng về mặt logic và thể hiện cho người sử dụng, trong khi server thực hiện việc xử lý phía sau và các chức năng về cơ sở dữ liệu
Hình 1.1 Mô hình client – server.
Cấu hình cơ bản của ứng dụng client - server :
Hình 1.2 Cấu hình cơ bản của ứng dụng client – server
Đối với ứng dụng trên Web, trình duyệt (browser) phục vụ như là client chung, gởi yêu cầu về một trang web, dịch ra ngôn ngữ HTML, và hiển thị nó cho người sử dụng Web server nhận yêu cầu thông qua giao thức dịch chuyển siêu văn bản (HTTP) và trả về thông
ClientRequest
ResponseServer
Database Server
- Quản lý dữ liệu
- Lệnh SQL truy xuất database
- Chương trình ứng dụngApplication Server
Client
Trang 11tin cần thiết trong dạng HTML mà client có thể hiểu được Tương tự như mô hình server, ta có thể phân bố việc xử lý ứng dụng và quản lý cơ sở dữ liệu thành từng phần với những mức độ khác nhau giữa máy client và máy server Hình1.3 mô tả cấu trúc của một ứng dụng web điển hình :
client-Hình 1.3 Mô hình web điển hình
So với ứng dụng client - server, ưu điểm chính của ứng dụng trên web là việc triển khai ứng dụng Với ứng dụng client-server, ta phải cài đặt lại thành phần trên client mỗi khi thay đổi và cập nhật ứng dụng Trong một ứng dụng web, với mỗi tính năng hay việc cập nhật mới ứng dụng, ta không phải đưa ra một chương trình thực thi mới trên mỗi máy desktop của người sử dụng Browser phục vụ như là client chung, cung cấp việc truy cập tới thông tin hiện có trên server Chi phí trong việc kiểm soát phiên bản, phân bố phần mềm, và quản trị hệ thống giảm đi rất nhiều đối với ứng dụng trên Web Hình 1.4 mô tả cấu hình
cơ bản của ứng dụng trên Web
Hình 1.4 Cấu hình cơ bản của ứng dụng trên Web
Trang 12II Ứng dụng trên Web :
Khác với ứng dụng chạy trên máy tính đơn lẻ khi mà việc xử lý được thực hiện trên mỗi máy tính, ứng dụng Web tập trung xử lý trên server (gồm một hay nhiều server) Vì browser chỉ đưa ra giao diện người sử dụng, toàn bộ ứng dụng được đặt trên server : (Hình 1.5)
Application Server (Server ứng dụng) : là phần mềm cung cấp các dịch vụ để hỗ trợ cho các ứng dụng Web làm chức năng kết nối người dùng đầu cuối với cơ sở dữ liệu cộng tác Nó hoạt động như một môi giới trung gian giữa trình duyệt Web và Database Server, nhờ đó không cần phải cài đặt ứng dụng đòi hỏi cao về mặt bảo trì cho người dùng đầu cuối
Trong hình 1.6 dưới đây, ta có một giao diện, những đối tượng bên trong để thực hiện công việc nào đó cùng với những dịch vụ Hình vẽ cho thấy tất cả những công việc chính đều đặt trên server, trên browser (client) chỉ còn mỗi user-interface
Web Browser Internet/Intranet Web server Network Application Server Network Database
Web Browser
Internet/Intrane t
Network
Networ k
User Interface
Application Server Data service objects
Web server
Business Objects Web Interface
Databas e
Trang 13Đối với Web server, thay vì user-interface, ta sẽ có Web-interface Đây là một lớp chương trình tương tác với Web server nhằm mục đích giao tiếp với client Web-interface đóng vai trò như lớp keo giữa những đối tượng và trang HTML được gửi tới browser của client Web-interface cung cấp HTML cho browser thông qua Web server và nhận những input từ user thông qua browser và Web server Có nhiều công nghệ được dùng để xây dựng Web-interface này, chẳng hạn như CGI, ISAPI, ASP Giữa những công nghệ này, có những ưu và nhược điểm khác nhau, tuỳ theo yêu cầu của ứng dụng mà ta sẽ chọn công nghệ thích hợp.
III CGI và ISAPI
1.CGI :
CGI (viết tắt của Common Gateway Interface) : là chuẩn để kết nối chương trình
ứng dụng với Web server Dữ liệu từ bảng biểu do người dùng điền vào trên trang Web được chuyển đến cho ứng dụng CGI, ứng dụng này sau đó sẽ gửi trả nội dung Web được tạo
ra theo yêu cầu ngược về cho trình duyệt (browser) của người dùng
Thuận lợi của ứng dụng CGI là tính phổ biến và dễ viết Ưùng dụng CGI có thể chạy trên mọi Web server thông dụng và có thể được viết bằng bất kỳ ngôn ngữ script nào như Perl hay Visual Basic hoặc ngôn ngữ biên dịch như C
Chương trình Script :
Script là bất cứ dạng chương trình thực thi nào hay chuỗi các chương trình mà nó có thể bắt đầu bởi Server để đáp ứng đối với yêu cầu của Client
Các biến môi trường :
Trước khi đưa ra chương trình gateway, Server khởi động một vài biến mội trường mà được tuần tự truy xuất tới chương trình gateway Trong thực tế, cơ chế được sử dụng là truyền thông tin đường dẫn mở rộng tới chương trình gateway Tên và ý nghĩa của các biến môi trường sẽ được trình bày như bảng sau :
Hình 1.6
Trang 14Biến Yùnghĩa
ALL_HTTP
-Tất cả những header HTTP không được phân tích theo một trong những biến dưới đây Những biến này có dạng :
HTTP_<header field name>.
AUTH_PASS -Lấy password tương ứng với REMOTE_USER được cung cấp
từ client Nó là một chuỗi kết thúc bằng ký hiệu null
AUTH_TYPE
-Một phương thức yêu cầu user name và password Nếu là xác nhận Basic, chuỗi sẽ là "Basic" Đối với WindowsNT Challenge/Response, chuỗi sẽ là "NTLM" Những xác nhận khác sẽ có những chuỗi khác tương ứng Nếu chuỗi rỗng thì không có xác nhận nào được sử dụng
CONTENT_LENGTH -Chiều dài (theo ki tự) của dữ liệu đang được gởi tới bởi client
dùng phương thức POST
CONTENT_TYPE -Cách thức thông tin được gửi đi từ client nếu sử dụng phương
PATH_INFO
-Thông tin thêm về đường dẫn, được truyền tới bởi client nó nằm trước chuỗi query và nằm sau tên script ví dụ :
http://www.hoahong.com/scripts/myscript.dll/mydir/myfile? Param, thì PATH_INFO sẽ là /mydir/myfile
PATH_TRANSLATED -Đây là giá trị của PATH_INFO, nhưng sẽ thay thư mục ảo
bằng thư mục vật lý trên đĩa
QUERY_STRING
-Bất cứ thông tin nào đi sau ký tự ? trong yêu cầu Chuỗi này
là đã được mã hoá, chẳng hạn : khoảng trắng sẽ được chuyển thành dấu + và ký tự không nằm trong bảng alphabet sẽ được chuyển thành dấu % cùng với một số hex tương ứng với ký tự đó trong bảng mã ASCII
REMOTE_ADDR - Địa chỉ IP của client
REMOTE_HOST - Hostname của client
REMOTE_USER - Tên mà user đang dùng để truy xuất server
REQUEST_METHOD - Phương thức yêu cầu HTTP, luôn là POST hoặc GET
SCRIPT_NAME -Tên của file script đang được yêu cầu (đang thực thi)
SERVER_NAME - Tên hay địa chỉ IP của server
SERVER_PORT - Cổng TCP/IP đã nhận yêu cầu
SERVER_PROTOCOL - Loại giao thức đang được dùng HTTP/1.0 hay HTTP/1.1
SERVER_SOFTWARE -Tên và version của web server mà chương trình CGI/ISAPI
đang chạy
Bảng các biến môi trường CGI
Trang 151.1 Đầu vào (Input)
Server dùng các biến môi trường để gởi đến CGI script những thông số của nó Hai biến môi trường chính dùng cho mục đích này là: QUERY_STRING and PATH_INFO
Đầu vào dữ liệu thật sự cho quá trình script đến từ một Form HTML Browser nhận
dữ liệu mà User đưa vào và định dạng nó như một chuỗi ghép của các ký tự ASCII được kết
hợp bởi các cặp thuộc tính name/value (tên/giá trị) Phần Name là tên của trường, Phần
value là những gì User đưa vào Form Dữ liệu này sẽ được xử lý theo nguyên tắc khoảng
trống được đổi thành cấc dấu + và mỗi cặp name/value được định dạng thành cấu trúc
name=value.
Form HTML xác định một trong hai phương pháp input là GET và POST
Phương pháp GET
Nếu Form dùng phương phương pháp GET, chương trình CGI nhận cặp name/value trong biến môi trường QUERY_STRING Chuỗi truy vấn (query)sẽ được nối vào URL của chương trình khi client gởi đi một yêu cầu tới server Đối với GET, ta có thể truy xuất chương trình trên Web server với một truy vấn mà không cần form Tuy nhiên, chiều dài chuỗi query chỉ giới hạn có 1KB
Phương pháp POST
Nếu Form dùng phương phương pháp POST, chương trình CGI nhận độ dài của dữ liệu mã hóa các cặp name/value trong biến môi trường CONTENT_LENGTH Chương trình sau đó đọc dữ liệu từ đầu vào chuẩn Server không nối con trỏ EOF đến cuối dữ liệu
Hơn nữa, script nhận kiểu dữ liệu đến trong biến môi trường CONTENT_TYPE Đây là kiểu nội dung MIME (Multipurpose Internet Mail Extensions) cấu hình trong Server,
thường là loại text/html
Đối với POST, chiều dài chuỗi query không giới hạn, hơn nữa ta không phải quan tâm về việc xén bớt dữ liệu của client hay server Tuy nhiên , chương trình sẽ phải đọc từ input chuẩn (như form )
1.2 Đầu ra (Output) :
CGI Script gởi đầu ra của nó đến STDOUT Đầu ra này thường là tài liệu ở dạng tập tin HTML mà Script phát ra Trong vài trường hợp, đầu ra nnày là một tham khảo đến vài dạng dữ liệu khác cho Server như là ảnh, văn bản thuần túy hay một đoạn âm thanh Trong những trường hợp như thế, đầu ra là tập hợp các lệnh đối với Server cho việc nhận đối tượng mong muốn
Đầu ra từ một CGI Script có hai phần tiêu đề (header) và dữ liệu (data)
Output header
Trang 16CGI script sẽ cho Server biết loại tài liệu gì nó sẽ gởi trở lại bằng cách gởi kèm một tiêu đề mô tả ngắn dạng văn bản ASCII Nếu đầu ra là tài liệu hoàn toàn, tiêu đề đưa ra là loại MIME Nếu đầu ra là có tham khảo đến tài liệu khác, tiêu đề sẽ là loại tham khảo URL.
Sau đây là một số Header HTTP :
- Chiều dài (bytes) của dữ liệu xuất (dữ liệu nhị phân)
- Kiểu nội dung MIME của dữ liệu xuất
- Ngày và giờ khi tài liệu không còn hợp lệ và nên được nạp lại bởi browser
- Tái định hướng server (nhưng không được gởi như là một phần của một header đầy đủ)
- Bật hoặc tắt cache cho tài liệu
- Trạng thái của yêu cầuĐặc điểm chung của header :
- Header sinh ra từ chương trình CGI không cần phải theo một thứ tự nhất định nào
- Khối header phải kết thúc với một dòng trắng :
Để biết ta đang làm gì với thông tin của header, server sẽ tìm kiếm khoảng trắng Bất kỳ thông tin nào được lấy trước dòng trắng là thông tin của header, mọi thông tin đi sau dòng trắng được giả định như là dữ liệu Nếu ta không đặt dòng trắng sau header, server sẽ giả định sai và toàn bộ thông tin được xem như là HTTP header, và sẽ sinh ra lỗi trên server
Trang 17Kieåu file (extension)
Content type (MIME)
HTMLTXTPSJPEGGIFAUMPEG
Server
Redirect
INTERNET
Hình 1.7
Trang 18Xuất Dữ liệu
Dữ liệu xuất theo tiêu đề và phải nằm trong một dạng như được thiết kế bởi tiêu đề Từ khi đầu ra được phục vụ trở lại browser, dữ liệu có thể là bất cứ dạng nào mà browser có thể chấp nhận
Dạng tốt nhất là tập tin HTML, bởi lẽ việc phục vụ xuất chương trình dạng HTML ta bao gồm khả năng nhúng các tham khảo đến các kiểu dữ liệu khác và trộn nó vào đầu ra của ta
1.3 Phương thức hoạt động của CGI Script
Server gọi chương trình CGI dựa vào thông tin nó nhận được từ browser Hình 1.8 trình bày cách thức hoạt động giữa browser, server và CGI Script như sau:
Browser gởi yêu cầu chương trình CGI thông qua server Server nhận yêu cầu từ browser, xem URL chỉ đến chương trình CGI và thực thi chương trình
Chương trình thực hiện vài tác vụ dựa vào đầu vào từ browser Những tác vụ như trên có thể là tính một giá trị, gọi vài chương trình khác trên hệ thống hay truy vấn dữ liệu
Chương trình định dạng kết quả hoạt động của nó theo cách mà server có thể hiểu được
Server sau đó đưa kết quả lại browser Rồi browser định dạng và hiển thị kết quả cho người đọc
Hình 1.8 Thông tin truyền từ browser đến chương trình CGI và quay trở lại
2 ISAPI :
ISAPI (Internet Server Application Programing Interface) : ra đời sau trong lĩnh vực giao diện động, là một API mở được phát triển bởi Process Software and Microsoft API này được thiết kế để tối ưu hiệu suất của những ứng dụng sinh ra trang động trên server Intranet/Internet
Về mặc chức năng, ISAPI rất giống với CGI, kỹ thuật viết mã script và ứng dụng cho CGI và ISAPI hoàn toàn giống nhau Tuy nhiên, ứng dụng CGI and ISAPI chạy rất khác nhau trên Windows NT
Serve r
Trang 19ISAPI cung cấp một tập hợp những giao diện cho phép ta tạo ra extensions và filters cho MSIIS (Microsoft Interner Information Server) IIS là web server đầu tiên hỗ trợ cho mô hình API này, tuy nhiên lập trình ISAPI không chỉ có ở IIS, hoặc đối với server chạy WinNT/Windows95, mà còn được hỗ trợ ở nhiều server khác.
Có hai loại ISAPI là ISAPI Extension và ISAPI Filter, cả hai có thể chạy trên bất kỳ Web Server nào có hỗ trợ ISAPI
Hình 1.9 mô tả cách hoạt động của một ứng dụng ISAPI trên Internet Browser chạy trên những máy tính client, truy xuất tới Web và hiển thị trang HTML chứa căn bản, đồ hoạ, ActiveX control và tài liệu Server cung cấp các dịch vụ (HTTP, FTP, gopher) và chạy những ứng dụng server extension sử dụng ISAPI (hay CGI)
2.1 ISAPI extensions :
Một ISAPI extension là một file DLL được nạp và gọi bởi một Web server (HTTP server) Internet server extension (hay còn gọi là Internet Server Applications - ISAs) được gọi từ browser của ứng dụng và cung cấp những chức năng tương tự như ứng dụng CGI
Khi lập trình CGI, đối với mỗi yêu cầu nhận được, một quá trình mới sẽ được tạo ra, sau đó thực thi và kết thúc Việc tạo ra và chấm dứt thực thi những quá trình này có thể dẫn tới việc sử dụng dư thừa thời gian và bộ nhớ
ISAPI extensions được tạo ra và chạy như những DLLs chứ không phải những tập tin thực thi Một ISAPI chạy như một thread trong cùng không gian của process hoặc bộ nhớ của Web server Kết quả là đoạn mã chỉ được nạp một lần dù có bao nhiêu instance đang tích cực tại một thời điểm nào đó cho trước Vì ISAPI extension chạy như là một thread của
WW Server running ISAPI Extensions and Filters
Add ftp,http and gopher support using WinInet
Asynchronous moniker transfer information without blocking
INTERNE
T
WWW Client running a Web Browser
Hình 1.9
Trang 20ISAPI Filter2
HTMLdocument
Client ISAPI request Client HTML request
ISAPI Filter1
ISAPI Extension
WebServer Process
Hình 1.10
Web server, nên nó có thể truy xuất trực tiếp tới không gian địa chỉ của Web server Do đó thông tin được chuyển từ Web server tới ứng dụng và từ ứng dụng tới Web server một nhanh chóng và dễ dàng
Tổng phí (overhead)của việc tạo thêm thread để xử lý yêu cầu ISAPI thường được
so sánh với tổng phí của việc tạo thêm process và truyền cho process dữ liệu mà nó yêu cầu
Thuận lợi của ISAPI Server Extensions
Những ISAPI server extension DLL (ISAs), sau khi được viết hoàn chỉnh sẽ được nạp và gọi bởi Web server Trong một trang Web, người sử dụng có thể điền vào form và click vào một button submit để gởi dữ liệu tới Web server và gọi ISAs ISAs có thể xử lý thông tin để đưa ra nội dung yêu cầu hoặc lưu giữ thông tin vào trong database Web server extension có thể sử dụng thông tin trong database để xây dựng những trang Web động, rồi hiển thị chúng trên máy tính của client Ứng dụng ISAs cũng có thể thêm vào tuỳ chọn khác về mặt chức năng rồi gởi dữ liệu cho client thông qua HTTP
Hạn chế của ISAPI Server Extensions
Tất cả ISAPI extension phải là thread-safe, do đó người lập trình phải hiểu rõ về việc sử dụng bộ nhớ Vì ứng dụng ISAPI truy xuất trực tiếp tới không gian địa chỉ của Web server, bất kỳ con trỏ sai lệch nào cũng có thể ghi đè lên thông tin server chính Như đã thấy trong sơ đồ của ISAPI Web server, thông qua những con trỏ, ISAPI extension có quyền truy xuất tới bất kỳ dữ liệu nào trong Web server Điều này có lợi khi hai ISAPI extension giao tiếp với nhau; tuy nhiên cũng dễ dẫn đến việc một extension làm hư hại dữ liệu của extension kia hoặc làm cho toàn bộ server bị dừng lại
Ngoài ra, khi lập trình ISAPI phải lưu ý trong việc giải phóng bộ nhớ Vì ISAPI DLL chạy như là một bộ phận của Web server, cả hai sẽ sử dụng cùng heap Đối với CGI , nếu ta quên giải phóng bộ nhớ, thì hệ điều hành sẽ thực hiện điều này khi chương trình chấm dứt Tuy nhiên đối với ISAPI, nếu ta sử dụng bộ nhớ được cấp phát, rồi sau đó không giải phóng bộ nhớ khi ra khỏi chương trình, thì bộ nhớ sẽ bị giữ cho tới khi process của Web server chấm dứt Cứ như vậy, mỗi lần được gọi ISAPI extension sẽ dùng thêm bộ nhớ, rồi cuối cùng extension sẽ làm dừng server
2.2 ISAPI Filters
Trong ISAPI còn có
một lớp những chương trình
không tương đương với CGI,
được gọi là ISAPI filter ISAPI
filter là DLL được nạp vào
mỗi lần Web server khởi động
và được gọi mỗi lần Web
server nhận một yêu cầu
Trang 21Hình 1.11
Windows NT server security process
Windows NT server security processISAPI Filter security
ISAPI Filter security Application
Web browser
Internet
Điều này cho phép ta có thể tuỳ biến dòng dữ liệu đi vào và đi ra Web server ISAPI Filter có thể nhận mọi loại yêu cầu Web server Khả năng ghi nhận được những yêu cầu về Web và xử lý những yêu cầu này trước (pre-procesing) hoặc sau (post-processing) khi Web server truy xuất chúng là một điểm mạnh của filter Hình trên (hình 1.5) mô tả giao tiếp giữa ISAPI Filters và ISAPI Extensions với những yêu cầu từ phía browser
Filter ghi nhận thông báo của những sự kiện, chẳng hạn như log vào hệ thống hoặc ánh xạ URL Khi sự kiện được ghi nhận xảy ra, filter sẽ được gọi và ta có thể giám sát và thay đổi dữ liệu (trên đường dữ liệu đi từ server tới client và ngược lại) ISAPI filter được sử dụng để kiểm soát những yêu cầu HTTP Là một công cụ hữu hiệu để tuỳ biến về mặt chức năng cho web server
Hình 1.11 mô tả vai trò của ISAPI filter trong hệ thống (như là một rào cản an toàn)
Trang 22CGI ProcessStandard
Out
Environmental Variables
WebServer Process
CGI ProcessCGI Process
Web Server Process
WinCG
I ProcessPrivate
Profile File
Private Profile File
WinCG
I Process
I Process
IV.So sánh và đánh giá
1 Hoạt động của một ứng dụng CGI :
Ưùng dụng CGI được biên dịch thành những chương trình thực thi (.exe) chạy độc lập Khi những chương trình này chạy, Windows NT sẽ tạo ra quá trình(process) độc lập mới cho mỗi yêu cầu của client, những yêu cầu này được xử lý bởi ứng dụng Tại bất kỳ một thời điểm nào cho trước, server sẽ hỗ trợ cho một quá trình độc lập của yêu cầu đang tồn tại Khi yêu cầu hoàn tất, server phải thực hiện một chuỗi những bước để hủy bỏ quá trình
CGI ban đầu được tạo ra trong môi trường UNIX, trong môi trường này, quá trình là đơn vị cơ bản của mọi hoạt động, hơn nữa một quá trình trên UNIX có overhead thấp hơn một quá trình trên Windows NT Trên WindowsNT, thread là đơn vị cơ bản của mọi hoạt động, và quá trình có overhead đáng kể Mỗi quá trình được cấp phát một vùng nhớ vật lý riêng, có thể là vùng nhớ có kích thước cố định (trang) hoặc không cố định, và được bảo vệ bằng những cơ chế bảo mật trên Windows NT Vì CGI yêu cầu mỗi chương trình chạy trong một quá trình riêng, nên ứng dụng CGI có overhead cao hơn ứng dụng ISAPI extension
2 ISAPI, CGI và WinCGI :
Đối với người dùng đầu cuối, sẽ không có gì khác nhau giữa một chương trình ISAPI (ở đây lấy ví dụ điển hình là một
ISAPI extension) và một chương
trình CGI hay WinCGI Tuy nhiên
đối với người lập trình, giữa chúng
có sự khác nhau và sự khác nhau
chính nằm trong giao diện giữa
server và chương trình
Đối với CGI, khi một
chương trình nhận được một yêu
cầu (request), thông tin về yêu cầu
đó được truyền đến như là những
biến môi trường, và đáp ứng được
trả về cho Web server theo
standard output Do đó, chương
trình CGI đòi hỏi ngôn ngữ mà ta
viết trên CGI có thể đọc và viết từ
standard input và standard output;
điều này gây khó khăn cho nhiều ngôn ngữ lập trình trên Windows khi được sử dụng để lập trình CGI
Để sử dụng những chương trình dựa trên Windows cho CGI, ta phải sử dụng WinCGI Khi Web server sử dụng giao diện WinCGI, dữ liệu được truyền tới lui nhờ vào tập tin mô tả riêng (private profile file) Trước đây, hầu hết ứng dụng Web trên Windows
Trang 23được viết bởi CGI và WinCGI Trong CGI và WinCGI có một lớp (layer), lớp này tách Web server ra khỏi ứng dụng Web Sự có mặt của lớp này làm cho hiệu suất giảm xuống.
Để loại bỏ điều này, ISAPI cho phép Web server giao tiếp với ứng dụng ISAPI thông qua cấu trúc Extension Control Block (ECB) ECB là một con trỏ tới mã và dữ liệu thích hợp mà ứng dụng ISAPI muốn
truy xuất Lý do mà chương trình ISAPI
chỉ cần một con trỏ để truyền thông tin
tới là vì tất cả DLL ISAPI chạy trong
không gian của quá trình của chính
Web server Đối với mỗi yêu cầu
ISAPI, Web server tạo ra một cấu trúc
ECB duy nhất, và truyền một con trỏ
cho cấu trúc này qua những hàm
ISAPI Bằng cách này, ISAPI
extension có thể nhanh chóng tìm ra
thông tin cần thiết - bằng việc sử dụng
một tham chiếu tới ECB mà server tạo ra cho nó Tạo ra và duy trì một cấu trúc dữ liệu thì dễ hơn và nhanh hơn là tạo ra một process mới
Một khác biệt nữa giữa CGI và ISAPI là sự chọn lựa ngôn ngữ lập trình để viết chương trình Những chương trình CGI có thể được viết bằng bất kỳ ngôn ngữ nào có thể xuất ra standard output, trong khi đó chương trình ISAPI chỉ có thể được viết bằng ngôn ngữ có thể tạo ra những file DLL
Khi được nạp, mã DLL của ISAPI là một phần của dịch vụ Web, và khi đó ứng dụng ISAPI hoạt động như một phần mở rộng
Một ứng dụng ISAPI cũng có những lợi thế là nhận được hỗ trợ của Win32 và chuẩn ODBC
Tuy nhiên, khác biệt cơ bản nhất giữa ISAPI và CGI là : chương trình ISAPI chạy trong không gian địa chỉ của chính Web server (in-process), còn chương trình CGI chạy theo từng quá trình riêng biệt (out-of-process) Do đó, chương trình ISAPI có thể truy xuất tới mọi tài nguyên có sẵn của Web server Sử dụng nhiều thread để đồng bộ công việc cho phép IIS sử dụng tài nguyên của hệ thống có hiệu quả hơn
CGI tạo ra một process riêng biệt cho mỗi yêu cầu Với CGI, mỗi lần một Web server nhận một yêu cầu, nó phải khởi tạo một process mới do đó đòi hỏi phải có một tài nguyên lớn để duy trì những process này Ưùng dụng ISAPI có overhead thấp hơn ứng dụng CGI, vì chúng không đòi phải tạo ra thêm những process và không phải thực hiện thời gian giao tiếp giữa những process
3 Overhead giữa CGI và ISAPI
Việc sử dụng những ứng dụng CGI cho thấy tốn nhiều thời gian xử lý và không gian nhớ hơn từ 3-5 lần so với ứng dụng ISAPI Tương tự như vậy, trên cùng một server và
Web Server Process
ISAPI Extension
Shared memory
ISAPI Extension
ISAPI Extension
Trang 24network, ud CGI chạy chậm hơn ứng dụng ISAPI DLL tương đương từ 3-5 lần Nếu chạy ứng dụng CGI hoặc ISAPI ta cần lưu ý đến việc giám sát overhead của chúng.
4 Tạo một ứng dụng Internet Server bằng ISAPI
Có thể sử dụng ISAPI để viết những ứng dụng về cơ sở dữ liệu (một hệ thống đặt mua hàng, hay một catalog bán hàng) Ta thu nhận thông tin từ user thông qua HTML form, và gởi lại trang HTML khác đã đựơc xử lý theo yêu cầu của user
Để chạy một DLL ISAPI server extension, user nhập URL trên browser, DLL sẽ chạy trên server và gởi dữ liệu HTML về lại cho client
Ví dụ: http://www.hoahong.com/register.dll?
Để cập nhật những tính năng mới cho DLL, ta ngừng dịch vụ Web server, thay thế DLL cũ bằng phiên bản mới trong thư mục dùng chung của nó trên server, rồi khởi động lại dịch vụ Yêu cầu sau đó của client sẽ nạp phiên bản DLL mới nhất Bằng tiến trình này, rất dễ dàng khi thêm vào chức năng mới cho DLL, và ta chỉ phải thực hiện cho một máy tính trong mạng
Trang 25Chương 2
ISAPI EXTENSIONS
I DLL (Dynamic-Link Library) trong ISAPI Extensions :
Mỗi ISAPI extension là một DLL, với những hàm sau :
BOOL WINAPI GetExtensionVersion (HSE_VERSION_INFO *pVer);
DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK *lpEcb);
GetExtensionVersion() chỉ được gọi một lần khi DLL được nạp và chỉ được dùng để cung
cấp thông tin version về DLL Thông tin này là số version và đoạn mô tả ngắn gọn về extension Nó được cất trong cấu trúc HSE_VERSION_INFO:
typedef struct _HSE_VERSION_INFO{
DWORD dwExtensionVerion;
CHAR lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN];
}HSE_VERSION_INFO, * LPHSE_VERSION_INFO;
HttpExtensionProc
Hàm thực hiện hầu hết công việc là HttpExtensionProc()
Cấu trúc của ECB
ECB được định nghĩa như sau (in và out cho biết dữ liệu là loại có thể được ghi vào hay đọc ra) :
typedef struct _EXTENSION_CONTROL_BLOCK {
DWORD cbSize; // IN
DWORD dwVersion; // IN
HCONN ConnID; // IN
DWORD dwHttpStatusCode; // OUT
CHAR lpszLogData[HSE_LOG_BUFFER_LEN]; // OUT
Trang 26CbSize Kích thước của ECB
DwVersion Thông tin về version của DLL
ConnID Một số được dùng bởi HTTP server để nhận dạng khối ECB, số
này là duy nhất và không thể sửa đổi DwHttpSatusCode Trạng thái gửi về cho HTTP server khi ISAPI extension đã
chạy, nó có thể là một trong những giá trị sau:
HTTP_STATUS_BAD_REQUEST HTTP_STATUS_AUTH_REQUIRED HTTP_STATUS_FORBIDDEN HTTP_STATUS_NOT_FOUND HTTP_STATUS_SERVER_ERROR HTTP_STATUS NOT_IMPLEMENTED
lpszLogData Bộ đệm ghi nhận thông tin
lpszMethod Giống như biến REQUEST_METHOD của CGI Có thể sử dụng cho
GET lẫn POST.
lpszQueryString Chuỗi một URL đã được mã hoá , giống như biến CGI
QUERY_STRING.
lpszPathInfo Tương tự như PATH_INFO
lpszPathTranslated Tương tự như PATH_TRANSLATE
cbTotalBytes Tương tự như CONTENT_LENGTH
cbAvailable Lượng dữ liệu có sẵn tại client được lưu giữ trong lpdData
Trang 27Nếu dữ liệu không có sẵn, ISAPI extension sẽ gọi hàm ReadClient.
lpbData 48KB đầu tiên được gửi tới từ client kích thước thực sự được
chỉ ra trong cbAvailable
lpszContentType Tương tự như CONTENT_TYPE
ECB.GetServerVariable()
Để lấy thông tin mà server truyền tới (chẳng hạn như tên một host từ xa đã được nối
kết, username và password .) ta cần gọi hàm GetServerVariable() của ECB
Hàm này được định nghĩa như sau :
BOOL (WINAPI * GetServerVariable)
(HCONN hConn,
LPSTR lpszVariableName,
LPVOID lpvBuffer,
LPDWORD lpdwSizeofBuffer);
Tham số Ý nghĩa
hconn -ID quản lý kết nối Biến này phải giống như biến tương tự đã khai báo
trong ECB, nếu không server sẽ đọc khối ECB sai.
lpszVariableName -Tên của biến đang tìm kiếm, sẽ được mô tả trong bảng 2.3.
lpvBuffer -Con trỏ tới buffer đang giữ đáp ứng của server
lpdwSizeofBuffer -Con trỏ tới kích thước của lpvBuffer khi hàm được gọi, nó xác định có
bao nhiêu bytes thực sự được đưa vào trong lpvBuffer.
lpszVariableName chứa tên của một biến CGI/ISAPI (biến môi trường) mà ta muốn đọc
Một ví dụ gọi hàm để tìm địa chỉ của user như sau :
bReturn = pECB -> GetServerVariable(pECB -> ConnID, “REMOTE_ADDR”, szBuffer,
&dwBufferSize);
Trong thường hợp này, szBuffer chứa địa chỉ IP của user, chẳng hạn: 206.34.194.10, sau khi hàm trả giá trị về
Để đơn giản, có thể sử dụng biến trực tiếp trong cấu trúc ECB Chúng cũng có thể
truy xuất từ hàm GetServerVariable.
Ví dụ :
pECB->lpszQueryString;
tương tự như szBuffer trong
bReturn = pECB->GetServerVariable(pECB->ConnID, “QUERY_STRING”, szBuffer,
&dwBufferSize);
Đưa dữ liệu ra cho client
Một hàm khác trong cấu trúc ECB là hàm WriteClient(), dùng để ghi dữ liệu ra cho
browser của client, được khai báo như sau :
BOOL (WINAPI * WriteClient)
Trang 28hConn : ID quản lý sự kết nối
lpvBuffer : dữ liệu mà ta muốn ghi ra cho client.
lpdwSizeofBuffer : khi gọi hàm, nó chứa chiều dài của lpvBuffer; khi trả giá trị về, nó
chứa số bytes thực sự được ghi Nếu không có lỗi thì 2 giá trị này như nhau
Ví dụ :
bReturn = pECB->WriteClient(pECB->ConnID,(LPVOID) rgBuff, &cb,0);
Đọc dữ liệu vào
Nếu dữ liệu client ghi lên sử dụng phương thức POST không thể sử dụng được đối
với lpbData trong ECB (kích thước dữ liệu lớn hơn 48K), ta cần lấy phần còn lại của dữ liệu bằng cách gọi một hoặc nhiều lần hàm ReadClient() :
Trong đó :
hConn : ID quản lý sự kết nối
lpvBuffer : nơi đặt những thông tin thêm.
lpdwSize : khi gọi ReadClient(), lpdwSize chứa kích thước của lpvBuffer Khi
trả về nó chứa số bytes thực sự được đọc
Ta tiếp tục gọi ReadClient() cho tới khi tổng số bytes đọc vào bằng với cbTotalBytes,
hoặc là sẽ không có dữ liệu nào trược trả về nữa
Ví dụ :
memcpy(lpszLargeBuffer,(LPCTSTR)ECB->lpdData,ECB->cbAvailable);
cbDataRead = ECB -> cbAvailable;
while (cbDataRead < ECB -> cbTotalBytes && ECB -> ReadClient (ECB>ConnID,(LPVOID) (lpszLargeBuffer+cbDataRead), &lpdwSize) && lpdwSize != 0)
được quyết định bởi những gì browser của client gởi đi trong header Content-Length:
Khi người sử dụng tại client bắt đầu upload dữ liệu đi, anh ta sẽ gửi đi một giá trị lớn header Content-Length:, để chỉ ra khối lượng dữ liệu mà mình muốn gửi Nếu extension chỉ lặp cho tới khi nhận được toàn bộ lượng dữ liệu này, ta sẽ gặp phải vấn đề khó khăn khi user huỷ bỏ upload dữ liệu giữa chừng hoặc nối kết mạng bị trục trặc khi dữ liệu mới đi
được nửa đường Lý do là vì ReadClient() chỉ FALSE khi có lỗi xảy ra, nó không coi những
vấn đề như mạng bị ngắt hay hủy bỏ upload của user là lỗi Khi mạng bị mất ngắt, hay user
hủy bỏ upload, ReadClient() sẽ trả về TRUE, chép dữ liệu trống vào trong buffer, rồi thiết
Trang 29lập tham số lpdwSize bằng 0 Bằng cách kiểm tra điều kiện này, ta sẽ bảo đảm không rơi
vào vòng lặp chờ vô tận khi kết nối bị ngắt
II MFC cho ISAPI
Để việc lập trình ISAPI dễ dàng hơn, Microsoft đưa ra một số class ISAPI trong MFC phiên bản 4.1 Những class áp dụng cho ISAPI extension là CHttpServer, CHttpServerContext, và CHtmlStream
1 CHttpServer
CHttpServer là class chính được dùng bởi MFC ISAPI extension Khi yêu cầu được gọi lần đầu tiên, một đối tượng CHttpServer sẽ được tạo ra để quản lý nó Khi đối tượng CHttpServer được tạo ra, nó sẽ sử dụng class CHttpServerContext để quản lý những
yêu cầu riêng, mỗi yêu cầu chạy như là thread riêng của đối tượng này Do đó, chỉ có một
instance của CHttpServer cho mỗi extension, nhưng có thể có nhiều instance CHttpServerContext.
Chức năng chính của CHttpServer là quản lý giao tiếp giữa web server và extension CHttpServer lấy yêu cầu từ Web server, truyền nó thông qua một parse map, và gọi hàm
thích hợp (với những tham số phù hợp với hàm) Ta sẽ nói đến cơ chế để thực hiện điều này
cũng như các hàm thành phần của CHttpServer trong những phần sau.
2 CHttpServerContext
Class CHttpServerContext là class được truyền cho mỗi hàm xử lý yêu cầu web Những hàm thành phần của CHttpServerContext là hiện thực của cấu trúc ECB Tuy nhiên,
class này không thực hiện tất cả những chức năng của ECB, sau đây là một số thành phần
của class CHttpServerContext :
Thành phần Ýnghĩa
m_pECB Con trỏ, được sử dụng khi cần truy xuất trực tiếp ECB.
m_pStream Con trỏ tới HTML stream
CHttpServerContext() Contructor
GetServerVariable() Giống như m_pECB->GetVariable() ngoại trừ việc ta không cần truyền
id của connection trong tham số của nó.
WriteClient() Giống như m_pECB->WriteClient() với ngoại trừ giống như trên.
ReadClient() Giống như m_pECB->ReadClient với ngoại trừ giống như trên.
ServerSupportFunction() Giống như m_pECB->ServerSupportFunction() với ngoại trừ giống như
trên.
Toán tử << Trái với việc sử dụng hàm WriteClient(), ta có thể sử dụng toán tử <<
đã được override Điều này làm cho việc xuất ra HTML trở nên đơn giản.
Trang 30Class này được CHttpServer sử dụng để ghi dữ liệu ra cho client Nó được tạo trong hàm CHttpServer::ConstructStream, và truyền cho ta như là thành phần của class CHttpServerContext Class CHtmlStream duy trì một bộ đệm (buffer) HTML trong bộ nhớ,
và tự động tạo thêm bộ nhớ khi cần và giải phóng nó khi kết thúc công việc Nó có một số hàm thành phần cho phép ta tăng kích thước của bộ đệm , nhưng không có hàm đọc bộ đệm
Hầu hết tương tác của ta qua class này là thực hiện với toán tử << Toán tử này ghi dữ liệu
thành chuỗi và tiến hành định dạng phép toán được đưa vào trên dữ liệu bằng số Hàm duy nhất cần quan tâm trên class này là constructor Nếu ta override hàm
CHttpServer::ConstructStream(), ta có thể trực tiếp gọi constructor của class CHtmlStream bằng cách sử dụng CHtmlStream(UNIT nGrowBytes), với nGrowBytes là kích thước bộ nhớ
cấp phát cho mỗi khối Ta có thể thay đổi điều này khi extension muốn xuất ra một đáp ứng dài hơn bình thường
Ưu điểm trong việc sử dụng MFC để tạo ứng dụng Internet Server
Visual C++ có ISAPI Extension Wizard giúp ta tạo ra ISAPI servers và filters Wizard này là một trong những lựa chọn có sẵn trong tab Project thuộc hộp thoại New của Visual C++ ISAPI Extension Wizard đơn giản hoá quá trình tạo server extension hay filter
Ta có thể chọn cách nối kết với MFC, có sử dụng filter, server extension hay cả hai, khai báo filter nào xử lý quyền ưu tiên nào, filter có sử dụng cơ chế bảo mật hay không Sau khi project được sinh ra, ta có thể thêm vào các chức năng tuỳ theo yêu cầu của ứng dụng
và tạo các parse map.
4 Xử lý Form và Parse Map
Form trên Web được sử dụng để thu nhận thông tin từ người sử dụng Thông tin này được gửi cho server thông qua URL trong đó kèm theo tên của DLL ISAPI và một danh sách những tham số dựa trên những gì user nhập vào trên form MFC giúp phân tích những
tham số này như sau : ta viết một hàm, khai báo tham số của nó, rồi sử dụng macro parse map để nối những đối số dòng lệnh với tham số của hàm này, kể cả những đối số tùy chọn
hoặc mặc nhiên Khi client gọi server, MFC sẽ trích những đối số ra và gọi hàm tương ứng, rồi MFC trả kết quả về cho client
Chi tiết về Form : xin xem trong phụ lục C
Các macro Parse Map
MFC dùng macro parse map để cho phép những hàm khác nhau trong cùng một DLL được gọi như là ISAPI extensions Nó cũng đưa ra một phương pháp lấy những biến trong form HTML và truyền chúng như tham số tới hàm đang được gọi Dưới đây, ta sẽ xét một số macro và hàm của những class của MFC ISAPI Extensions đã được nói ở trên
Trang 31Các macro parse map bao gồm : BEGIN_PARSE_MAP, ON_PARSE_COMMAND,ON_PARSE_COMMAND_PARAMS, DEFAULT_PARSE_COMMAND vaø
END_PARSE_MAP.
BEGIN_ PARSE_MAP và END_PARSE_MAP:
BEGIN_PARSE_MAP đánh dấu nơi bắt đầu macro Tham số của nó gồm : class chứa hàm được ánh xạ ra của nó và class cha CHttpServer END_PARSE_MAP chỉ chứa một tham số là tham số đầu tiên trong BEGIN_PARSE_MAP.
Giả sử class cha là CHttpServer và derived class có tên là MFCRedirExtension, ta
phải bằng nhau, hoặc để mặc định là Default.
ON_PARSE_COMMAND cho phép những loại tham số (trong tham số thứ ba) như sau :
Loại macro Ý nghĩa
ITS_LPSTR Con trỏ tới một chuỗi ITS_I2 Kiểu short
ITS_I4 Kiểu long ITS_R4 Kiểu float ITS_R8 Kiểu double ITS_EMPTY Không truyền bất kỳ tham số nào.
Ví dụ :
ON_PARSE_COMMAND(Default,MFCRedirExtension,ITS_LPSTR)
Ta định nghĩa Default() là thành phần của MFCRedirExtension và lấy tham số là bộ
đệm một chuỗi Tất cả hàm được gọi bởi, parse map phải có tham số đầu tiên là con trỏ trỏ
tới class CHttpServerContext.
Trang 32Hàm thành phần Default() là một trong những hàm quan trọng nhất của class CHttpServer Ban đầu, wizard của Visual C++ sẽ tự động tạo ra những dòng sau:
void CTestExtension::Default(CHttpServerContext* pCtxt)
{
StartContent(pCtxt);
WriteTitle(pCtxt);
*pCtxt << _T("This default message was produced by the Internet");
*pCtxt << _T(" Server DLL Wizard Edit your CTestExtension::Default()");
*pCtxt << _T(" implementation to change it.\r\n");
Đối tượng CHttpServerContext là xác định duy nhất output tới web server vào một thời
điểm nàođó, nhiều thread có thể gọi cùng một hàm để ghi ra client Làm sao web server có thể biết output nào cần đưa ra cho client? Web server sẽ tạo ra cấu trúc ECB và truyền nó
cho mỗi yêu cầu MFC che dấu ECB trong đối tượng CHttpServerContext và truyền cho ta
con trỏ tới nó Do đó ta phải truyền đối tượng này cho bất kỳ hàm nào ta muốn đọc hay ghi
ra cho client
CHttpServer::StartContent
Đầu tiên, trong hàm Default() sẽ gọi StartContent(pCtxt) Vì CHttpServer::StartContent() ghi dữ liệu ra cho client, nó sẽ truyền môït con trỏ tới đối tượng CHttpServerContext , đối tượng này đã được tạo ra để quản lý các yêu cầu
Truyền dữ liệu
Không như hàm thành phần CHttpServer::WriteClient(), CHtmlStream không ghi dữ liệu ra client trực tiếp Thay vào đó, khi ta đặt dữ liệu vào trong CHtmlStream, nó sẽ để dữ
liệu vào một bộ nhớ đệm (class sẽ cấp phát bộ nhớ khi ta ghi dữ liệu vào) Khi extension
kết thúc, CHttpServerContext (thông qua CHttpServerContext :: WriteClient() ) sẽ ghi ra
những gì đã được cất giữ bên trong đối tượng CHtmlStream, và CHtmlStream giải phóng bộ
nhớ đã cấp phát cho stream (stream là dòng dữ liệu được xuất ra thông qua standard ouput)
Trong đoạn mã chương trình trên, CHttpServerContext đã override toán tử << để nó có thể
gởi chuỗi xuất ra trong trang HTML Hàm WriteTitle() và EndContent() ghi tag HTML ra
trong stream để chúng có thể được gởi tới client Những hàm này cũng dùng toán tử
Trang 33BOOL ServerSupportFunction(DWORD dwHSERequest,
LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType);
Trong đó :
dwHSERequest : kiểu request đã được định nghĩa mà ta yêu cầu server thực hiện, được mô tả trong bảng 1.4
lpvBuffer : một chuỗi trạng thái tuỳ chọn cho yêu cầu Nếu là NULL thì mã trả về là 200
OK Điều này có nhiều ý nghĩa trong việc đưa thông báo cho browser
lpdwSize : chỉ sử dụng khi yêu cầu HSE_REQ_SEND_RESPONSE_HEADER Khi gọi hàm, nó chứa kích thước của lpvDataType, khi trả về nó chứa số byte thực sự được ghi lên
header
lpdwDataType : là bất kỳ header tùy chọn nào mà ta muốn trả về cho client, mặc nhiên là NULL
Bảng những giá trị của tham số dwHSERequest :
- gởi một header HTTP về cho client Nếu dữ liệu có trong lpdwDatatype, nó cũng được đặt trong gói header Thường sử dụng cho HTTP cookies
- Lúc trả về, hàm sẽ ánh xạ đường dẫn luận lý được chỉ bởi lpvBuffer thành đường dẫn vật lý
- Báo cho server rằng extension đã thực hiện
Ta có thể truyền hằng HSE_REQ_SEND_URL_REDIRECT_RESP cho dwHSERequest để yêu cầu server cấp phát việc tái định hướng cho ta Cũng có thể truyền URL đích nơi mà ta muốn client tái định hướng tới
III Sử dụng ISAPI Extension để truy xuất database
1 ODBC và DAO
Khi một ISAPI extension đang chạy, nó phải chia sẻ tài nguyên với process cha (là ISAPI server) và những extension khác đang chạy bằng những thread khác Có nhiều phương pháp đưa ra để truy xuất database dựa trên tài nguyên chung Chẳng hạn một thread
Trang 34mở database DAO và thực hiện một query Khi ISAPI extension khởi tạo đối tượng DAO, nó sẽ xóa đối tượng DAO trước, và query của user trước sẽ mất Vấn đề này không chỉ tồn tại ở DAO, vấn đề tương tự cũng nảy sinh khi truy xuất dữ liệu bằng những phương pháp khác dùng COM.
Để giải quyết điều này, ta sẽ không sử dụng DAO mà dùng driver ODBC (ODBC API) ODBC là một driver thread-safe
Thông qua ODBC, ta có thể truy xuất đến bất kỳ database nào nếu như nó có hỗ trợ driver này Có thể kể tên một số như : MSAccess, MS Foxpro, SQL Server, hay Oracle
2 Sử dụng MFC để truy xuất database
Microsoft Foundation Classes (MFC) cho phép người phát triển chương trình tạo ra ứng dụng trên Windows mà không cần phải biết cấu trúc bên dưới của Windows Microsoft đã phát triển MFC cho ODBC API Những class này thể hiện phương pháp tiếp cận hướng đối tượng sử dụng ODBC API Những class MFC cho OBDC API làm cho việc lập trình dễ dàng hơn, việc liên kết tới MFC làm cho ứng dụng được mở rộng
Class ODBC của MFC : CDatabase và CRecorset
Recordset : là một khối dữ liệu, tập hợp của nhiều hàng trong một bảng (recordset
còn được gọi là rowset) Có hai loại recordset: snapshots và dynasets Cả hai đều được class CRecordset hỗ trợ Mỗi loại có tính chất chung của recordsets, nhưng cũng có những tính chất mở rộng
Snapshots : cung cấp dữ liệu tĩnh (rowset tĩnh), có ích cho những bản báo cáo hay
những tình huống khi ta muốn xem dữ liệu tại một thời điểm xác định nào đó
Dynasets : rowset động Có ích khi ta muốn việc cập nhật dữ liệu được thực hiện bởi
người khác, để có thể nhìn thấy dữ liệu trong recordset mà không phải query lại hay làm tươi recordset
Hai class ODBC chính của MFC là CDatabase và CRecorset Đối tượng của class CDatabase tiêu biểu cho những kết nối với data source, và đối tượng của CRecordset tiêu biểu cho những recordset (rowset) Ta ít khi sử dụng class được derive từ CDatabase nhưng thường xuyên derive class từ CRecorset để so trùng cột trong những bảng của database
Hình 2.15 Mối quan hệ class MFC ODBC database
ODBC connection
ODBC rowset
Database Dynaset hoặc
snapshot
Trang 35Sau đây là một số hàm quan trọng của class CRecordset :
AddNew - Chuẩn bị thêm một record mới vào bảng
Update - Hoàn tất tác vụ AddNew và Edit bằng cách lưu dữ liệu mới
hoặc đã được sửa vào trong data sourceDelete - Xoá record hiện hành khỏi recordset
Edit - Chuẩn bị thực hiện những thay đổi trên record hiện hành
IsOBF - Xác định liệu recordset có được định vị trước record đầu tiên
không IsEOF - Xác định liệu recordset có được định vị sau record đầu tiên
không MoveNext - Thiết lập record hiện hành cho record kế tiếp hoặc rowset kếMoveFirst - Thiết lập record hiện hành cho record đầu tiên trong recordset.MoveLast - Thiết lập record hiện hành cho record cuối cùng trong recordset
hay cho rowset cuối
MovePrev - Thiết lập record hiện hành cho record ngay trước hoặc cho
rowset trước
GetDefaultConnect - Lấy chuỗi kết nối mặc định cho data source mà trên đó thiết lập
recordsetGetDefaultSQL - Lấy chuỗi SQL mặc định
DoFieldExchange - Chuyển đổi dữ liệu giữa field dữ liệu trong recordset và record
tương ứng trên data sourceGetStatus - Lấy chỉ số của record hiện hành trong recordset và trạng thái
tính cuối cùng
GetRecordCount - Xác định record được đánh số cao nhất khi user di chuyển qua
các record
GetODBCFieldCount - Lấy số field trong một đối tượng recordset
GetODBCFieldInfo - Lấy thông tin về field trong một recordset
Trang 363 ISAPI trong việc truy xuất database :
Hình sau mô tả quá trình truy xuất dữ liệu của một chương trình CGI/ISAPI :
a) Ghi dữ liệu : sử dụng hàm CDatabase::OpenEx()
Giống như CDatabase::Open(), OpenEx() tạo một kết nối tới database Database::OpenEx() thường được dùng cho lập trình ISAPI vì có thêm tham số CDatabase::noOdbcDialog Khi sử dụng hàm CDatabase::Open(), nếu tham số không xác định đủ thông tin để tạo kết nối ODBC (như quên hoặc sai user name hay password), MFC sẽ tự động mở hộp thoại kết nối ODBC để yêu cầu thêm thông tin từ người dùng
Đối chương trình trên Web, người lập trình sẽ không muốn có một dialog được mở ra để chờ người dùng nhập dữ liệu vào Vì Web server chạy như một dịch vụ nên sẽ không có một dialog nào được mở nếu không thiết lập “Interative with Desktop” trong Service Control Panel
Trang 37}
Để kiểm tra một recordset rỗng, ta dùng hàm IsBOF() trong class CRecordset Hàm chỉ trả
về TRUE nếu không có record trong recordset vì khi recordset lần đầu tiên được mở, con trỏ sẽ chỉ tới record đầu tiên (nghĩa là IsBOF() = FALSE) Nếu không có recordset rỗng, ta sẽ ghi dữ liệu vào databse dùng lệnh SQL rồi thông báo cho người dùng rằng tác vụ ghi đã thành công
b) Xử lý ngoại lệ (exception) :
Có thể có nhiều tình huống không mong đợi sẽ diễn ra khi chương trình đang chạy như hết bộ nhớ, hết không gian đĩa, cố gắng ghi hay đọc dữ liệu lên vùng nhớ đang được bảo vệ
Thay vì phải viết code để kiểm tra và xử lý lỗi, C++ đưa ra một phương pháp rất mạnh nhưng dễ sử dụng cho việc xử lý lỗi hay ngoại lệ Đó là những lệnh xử lý ngoại lệ C++ chuẩn như : try, catch và throw
Định dạng của khối try/catch là :
try
{
// đoạn mã mà ta muốn thực hiện
// có thể có lỗi trong khi thực hiện
Trang 38// catch bất kỳ exception nào khác
}
// đoạn mã thực thi tiếp theo của chương trình nếu ta không thoát từ khối catch
Khối “try” của đoạn mã thực hiện những gì ta muốn thực hiện Khi thực hiện, ta nghi ngờ sẽ có lỗi nào đó xảy ra; nếu có lỗi đó, exception trong khối catch sẽ được gọi để xử lý
Không phải mọi exception đều là lỗi, nhưng là những đáp ứng được định nghĩa cho những tình huống không mong đợi
Như trong ví dụ, exception mà ta cố gắng bắt được định nghĩa trong MFC là CDBException Nếu một kết quả không mong đợi được trả về bởi một trong những lệnh gọi database ODBC mà được che trong class CRrecordset thì CDBException được gọi
Nếu ta giữ một loại exception đặc biệt nào đó với lệnh catch, đoạn mã trong khối catch sẽ được thi hành Chương trình thực thi sẽ ngưng tất cả các khối catch khác nếu một trong các khối catch trả về hoặc truyền exception cho khối try/catch kế
c) Đọc dữ liệu :
Khi dữ liệu đã có trong database, ta có thể muốn truy xuất nó Trong trường hợp này,
ta cũng sử dụng những hàm truy vấn cơ sở dữ liệu ODBC
Trang 39_Chương 3
CHUẨN ODBC INTERNET INFORMATION SERVER
-I Chuẩn ODBC (Open Database Connectivity)
Có rất nhiều hệ thống database khác nhau, nếu không có một chuẩn chung để giao tiếp giữa những hệ database này thì khi ứng dụng chuyển đổi từ hệ database này sang hệ database khác, mã của chương trình phải thay đổi lại cho phù hợp Để giải quyết tình trạng này, người ta đã đưa ra một chuẩn để các kiểu database khác nhau có thể giao tiếp được, đó là ODBC (Open DataBase Connectivity)
Chuẩn ODBC, là một tập mở rộng của những thư viện liên kết động (DLL), cung cấp giao diện lập trình ứng dụng cơ sở dữ liệu chuẩn ODBC dựa trên phiên bản được chuẩn hoá của SQL ODBC là một lớp nằm giữa chương trình ứng dụng và hệ thống database Với ODBC và SQL, ta có thể viết mã truy xuất đến cơ sở dữ liệu mà không phụ thuộc vào bất kỳ phần mềm cơ sở dữ liệu nào
Chuẩn ODBC không chỉ định nghĩa luật văn phạm của SQL mà còn định nghĩa giao diện lập trình của ngôn ngữ C cho một databse SQL Do đó, đối tượng C hay C++ có thể truy xuất tới bất kỳ DBMS nào có driver ODBC
ODBC là lớp phục vụ giao tiếp giữa chương trình ứng dụng và hệ điều hành cũng như hệ thống file của database ODBC nhận những yêu cầu truy xuất thông tin từ chương
trình ứng dụng, chuyển nó thành ngôn ngữ mà database engine hiểu được để truy xuất thông
tin từ database Như vậy, nó cho phép chúng ta phát triển tập hợp các function và method để truy xuất đến database mà không cần phải hiểu sâu về database đó
Ví dụ, MS Access cho phép chúng ta liên kết (link) hay gắn (attach) một bảng đến database Khi thực hiện điều này, Access sẽ yêu cầu chúng ta chọn loại database (database mà Access trực tiếp hỗ trợ), nếu không có loại database phù hợp chúng ta có thể chọn ODBC Khi chọn ODBC, nó sẽ liệt kê tất cả các cấu hình khác nhau mà chúng ta đã thành lập, và
chọn một trong số đó bất kể database engine nào.
Khi ứng dụng làm việc với ODBC, nó làm việc với data source và database engine
mà nó tham khảo Khi thiết lập cấu hình cho client mà cài đặt những kết hợp driver với database Những kết hợp này sẽ được đặt tên và được sử dụng khi chúng ta muốn yêu cầu kết nối để truy xuất đến database đó Những kết hợp giữa database và driver gọi là những Data Source Name hay những DSN Khi muốn mở một database thông qua ODBC, chúng ta phải cung cấp DSN, UserID và Password ODBC sẽ lấy những thông số mà chúng ta đã thiết lập cấu hình sẵn (trong Control Panel - ODBC32) để tạo kết nối
Những thành phần chung của DSN :
Trang 40- DSN : Tên DSN mà chúng ta đã đặt khi thiết lập cấu hình ODBC
- UID : UserID được sử dụng để login vào database
- PWD : Password được sử dụng khi login
Như vậy, để truy xuất đến các database thông qua ODBC, ta phải cài đặt driver cho database đó ODBC có nhiều driver để hỗ trợ cho các database khác nhau nhằm chuyển các bảng tính hay các tập tin văn bản thành data source Hệ điều hành căn cứ vào thông tin được ghi bởi ODBC Administrator trong Registry để xác định cấp của ODBC driver giao tiếp với data source
Việc nạp ODBC driver là "trong suốt" (transparent) đối với chương trình ứng dụng Trong môi trường mạng, ODBC đảm nhận luôn cả việc xử lý những vấn đề truy xuất dữ liệu trên mạng như việc truy xuất đồng thời hay giải quyết tranh chấp
Tóm lại, ODBC là một giao tiếp lập trình chuẩn cho người phát triển ứng dụng và nhà cung cấp database Trước khi ODBC trở thành một chuẩn không chính thức cho các chương trình ứng dụng trên Windows giao tiếp với các hệ thống database, người lập trình phải sử dụng các ngôn ngữ riêng cho mỗi database mà họ muốn kết nối tới Khi ODBC ra đời thì người lập trình không còn bận tâm về điều này nữa, họ có thể truy xuất đến các database khác nhau bằng các thủ tục và hàm như nhau Mã của chương trình ựng dụng không thay đổi khi data source chuyển từ hệ thống database này sang hệ thống khác (ví dụ từ Oracle sang SQL server)
Ưu điểm và nhược điểm của ODBC
Vì ODBC cung cấp việc truy xuất đến bất kỳ dạng database thông dụng có sẵn, do đó tạo nên sự uyển chuyển trong những ứng dụng Ta có thể chuyển ứng dụng từ hệ thống database này sang hệ thống database khác mà không tốn nhiều chi phí và công sức DSN của ta có thể tham khảo đến bất kỳ một database nào Điều này cho phép ta có thể tham khảo đến bất kỳ một database nào Như vậy, ta có thể phát triển ứng dụng theo một hệ thống database này (chẳng hạn như Microsoft Access) nhưng lại biến đổi thành sản phẩm sử dụng hệ thống database khác (ví dụ như Microsoft SQL Server) bằng cách đơn giản là thay đổi driver được sử dụng DSN mà chúng ta định nghĩa trong ứng dụng
Việc gọi hàm qua lớp ODBC đến database engine không phải là không tổn phí ODBC phải hỗ trợ khả năng chuyển đổi các hàm được gọi từ ứng dụng, việc này cần phí tổn cho việc xử lý và làm quá trình truy xuất database chậm đi Hơn nữa, ODBC không hỗ trợ việc truy xuất cơ sở dữ liệu đối tượng (Object Database)
II Internet Information Server (IIS)
1 Web Server (HTTP server)
Là một chương trình được nối với Web, cung cấp tài nguyên dựa trên những yêu cầu từ browser Tài nguyên được yêu cầu luôn được xác định bởi một URL
Đối với bất kỳ một Web site nào, trung tâm của nó là back-end server, là một bộ phận chương trình dùng để hoàn thành các nhiệm vụ xử lý mà chương trình đó được thiết kế