Saturday, July 21, 2012

Làm phòng chat với ASP

Khi bạn truy xuất đến trang web, ví dụ http://www.vietchat.com/, thì trình duyệt web sẽ tải về đoạn mã java và chạy tại máy của bạn. Chương trình java này sẽ tạo một kết nối bằng đường socket của TCP/IP đến máy chủ. Kết nối này được xác lập và định vị bằng địa chỉ IP máy chủ, địa chỉ IP máy trạm, và cổng (port) cố định nào đó. Kết nối này là kết nối 2 chiều, nghĩa là dữ liệu sẽ được chuyển từ máy chủ về máy trạm và ngược lại. Khi nào bạn còn hiện diện trong phòng chat thì kết nối này còn duy trì. Chương trình java trên máy của bạn sẽ truyền nội dung chat đến máy chủ và từ máy chủ về máy bạn qua kết nối này. Loại phòng chat này chạy rất nhanh và có nhiều chức năng vì đây là những kết nối liên tục (không bị đứt quãng giữa chừng). Tuy nhiên nhược điểm là không dùng được cho người dùng internet ở bên trong 1 bức tường lửa (firewall) hay proxy server, vì firewall sẽ giới hạn người dùng chỉ được sử dụng 1 số cổng nhất định nào mà thôi. Firewall Việt Nam chỉ cho sử dụng một số cổng chuẩn (phổ biến) là cổng 80 (dùng cho HTTP), cổng 21 (dùng cho FTP)…Nếu chương trình sử dụng một cổng nằm ngoài danh sách cho phép của firewall VN thì coi như là bị khóa.
Để tránh nhược điểm này, người ta nghĩ ra cách làm phòng chat bằng HTML thuần tuý. Nguyên tắc như sau:

Trên máy trạm bạn sẽ truy xuất 1 trang web có ít nhất 2 frame, một trong 2 frame đó sẽ có form cho phép bạn nhập dữ liệu.
Dữ liệu bạn nhập vào được chuyển về máy chủ và ghi xuống một biến ở cấp application (biến ở cấp application là biến mà mọi người đang kết nối với máy chủ đều truy xuất được).
Frame thứ hai sẽ lấy thông tin chat từ máy chủ qua biến cấp application này. Do nội dung chat luôn luôn thay đổi nên frame thứ hai sẽ được đặt ở chế độ làm tươi liên tục. Nếu bạn đặt thời gian làm tươi là 5 giây thì cứ sau mỗi 5 giây, bạn mới thấy được những câu chat mới được gửi từ những người khác trong phòng chat.
Tuy nhiên chương trình chat kiểu này có nhược điểm: cách truyền dữ liệu theo kiểu trang web (nghi thức HTTP) là đường truyền 1 chiều, nghĩa là chỉ có máy trạm là chủ động ra yêu cầu cần dữ liệu, máy chủ nhận được yêu cầu thì trả lời, không có trường hợp ngược lại là máy chủ yêu cầu dữ liệu từ máy trạm. Chính lý do này ta cần phải làm tươi (refresh) nội dung của trang web trên máy trạm.

Thực hiện:

Cấu trúc trang web
Trong bài viết này, chúng tôi sẽ hướng dẫn cách làm 1 phòng chat bằng ngôn ngữ ASP. Cửa sổ chat gồm có 3 phần: 2 phần như đã nói trên, đó là phần nội dung chat và phần nhập liệu. Phần thứ ba là hiển thị danh sách những người đang có mặt trong phòng chat.

Do cửa sổ chat có 3 phần nên ta cần 3 frame như sau:



ASP CHATROOM









Sorry, your browser does not support frames.



Bạn lưu đoạn mã trên vào file frames.html, đây là phần khung chính của toàn bộ chatroom. Trong đó frame thứ nhất tên là users sẽ chứa danh sách users, frame này sẽ gọi file users.asp trên server. Frame này sẽ làm tươi sau mỗi 25 giây nên cần có đoạn mã làm tươi như sau:









Frame thứ hai là nội dung chat, tên frame là chat và chỉ đến file chat.asp trên server được làm tươi sau mỗi 10 giây. Bạn đánh đoạn code sau đây và lưu thành file có tên chat.asp:









Frame cuối là để nhập dữ liệu tên là input sẽ gọi file input.asp trên server mỗi khi user nhập dữ liệu và nhấn phím enter. Vì cần phải nhập dữ liệu bằng form, nên file input.asp sẽ có chứa form như sau:












Đến đây bạn đã có tất cả 4 files: frames.html, users.asp, chat.asp, và input.asp. Bây giờ xin mời bạn xem tiếp cách tổ chức dữ liệu trên máy chủ.

Tổ chức dữ liệu
Danh sách users và nội dung chat sẽ được chứa trong array. Giả sử ta chỉ cần giữ lại 20 câu chat sau cùng, ta cần array 20 phần tử. Và để đơn giản, ta giới hạn số người chat nhiều nhất là 10 người ==> cần array 10 phần tử. Cả hai biến này đều ở cấp application vì mọi users đều truy xuất được. Ta đặt tên 2 biến này là Application(“content”) và Application(“users”). Do nội dung chat là 1 array được dùng xoay vòng, ta cần 1 biến Application(“pointer”) để chỉ phần tử nào là mới nhất trong array. Tuy nhiên, cần thêm 1 biến đếm số users đang hiện diện trong phòng chat, biến này kiểu integer: Application(“count”). Để truy xuất phần tử thứ n trong array Application(“content”) ta dùng cú pháp: Application(“content” & n).

Để tiện cho việc lập trình, mỗi user cần lưu trữ 1 biến cấp session chứa tên đăng ký lúc vào phòng chat: Session(“nick”).

Các biến cấp application và cấp session sẽ được khởi tạo trong global.asa như sau:



Sub Application_OnStart

Application(“CHATSIZE”) = 20
Application(“MAXUSER”) = 10

u_array = ARRAY(“”, “”, “”, “”, “”, “”, “”, “”, “”, “”)
REDIM u_array(Application(“MAXUSER”))
Application(“users”) = u_array

c_array = ARRAY(“”, “”, “”, “”, “”, “”, “”, “”, “”, “”)
REDIM c_array(Application(“CHATSIZE”))
Application(“content”) = c_array

Application(“count”) = 0
Application(“pointer”) = 0

End Sub

Sub Application_OnEnd

End Sub

Sub Session_OnStart

Session.TimeOut = 10
Session(“nick”) = “”

End Sub

Sub Session_OnEnd

End Sub



Lập trình cho máy chủ
Lập trình cho máy chủ gồm những phần nhỏ sau đây: thêm 1 câu chat mới vào nội dung, hiển thị nội dung của phòng chat, và hiển thị danh sách các user đang ở trong phòng chat.

1. Thêm câu chat mới:

<%

dim msg
dim current_pointer

msg = Request(“input_text”)

‘không cho phép dùng html trong phần nội dung chat
msg = Server.HTMLencode(msg)

‘thay thế các hình cười và khóc
msg = REPLACE(msg, “:)”, “”)
msg = REPLACE(msg, “:(“, “”)

‘nối thêm tên của người gửi vào
msg = “” & Session(“nick”) & “: ” & msg

‘Lưu câu chat mới vào array
Application.lock
current_pointer = Application(“pointer”)
Application(“content” & current_pointer) = msg
Application(“pointer”) = (current_pointer + 1) MOD Application(“CHATSIZE”)
Application.unlock

%>

Bạn nối phần mã này vào file input.asp. Lưu ý: biến pointer sẽ tăng lên 1 để chỉ phần tử kế tiếp trong array content, nhưng khi đến phần tử cuối cùng thì phải quay về phần tử đầu tiên là 0, vì trong đoạn code trên có phần modify cho CHATSIZE.

2. Hiển thị nội dung chat

Vì array content được dùng xoay vòng, nội dung chat sẽ được hiển thị từ phần tử pointer đến phần tử cuối trong array, sau đó từ phần tử 0 đến phần tử trước pointer (nếu pointer > 0).

<%

for i = Application(“pointer”) to Application(“CHATSIZE”) – 1
if Application(“content” & i) “” then
Response.write Application(“content” & i) & “

end if
next

if Application(“pointer”) > 0 then
for i = 0 to Application(“pointer”) – 1
if Application(“content” & i) “” then
Response.write Application(“content” & i) & “

end if
next
end if

%>

Bạn nối đoạn mã này vào phần BODY của file chat.asp. Lưu ý: sau mỗi câu chat cần phải xuống hàng mới do đó trong đoạn mã trên, ta nối thêm kí tự xuống dòng “
” cho mỗi câu chat.

3. Hiển thị danh sách users:

<%

Response.write “

Co ” & Application(“count”) & ” nguoi trong phong chat



for i = 0 to Application(“count”) – 1
if Application(“users” & i) “” then
if Session(“nick”) = Application(“users” & i) then
Response.write “<” & Application(“users” & i) & “>

else
Response.write Application(“users” & i) & “

end if
end if
next

%>

Bạn chép đoạn mã này vào phần thân (body) của file users.asp. Lưu ý: tên của bạn sẽ được in nằm giữa hai dấu .

4. Logon và logoff:

Bây giờ đến phần khá quan trọng là logon và logoff. Khi người dùng vào phòng chat của bạn, trước họ sẽ được nhắc nhập vào tên “nickname” và khi người sử dụng rời khỏi phòng chat họ sẽ quay về trang web này. Ta cần phải có form để người dùng nhập nickname như sau:



ASP CHATROOM


Chao mung cac ban den voi ASP Chatroom


Moi ban nhap vao ten se dung trong luc chat (chi su dung chu, so va cac ki tu -, _)









Bạn lưu nội dung trên đây vào file index.asp, sau đó thêm đoạn mã bên dưới vào phần đầu của file để thêm người mới vào danh sách users khi logon:

<%

dim error
dim nick
dim numuser
dim current_pointer
dim error_msg(2)

nick = Request(“nickname”)

error_msg(0) = “—– ” & nick & “ vua vao chatroom —–”
error_msg(1) = “

—– Phong chat het cho, xin moi quay lai sau —–


error_msg(2) = “

—– Ten nay da co nguoi su dung, xin chon ten khac —–



‘chỉ thi hành đoạn mã này nếu user truy xuất trang này bằng nhấn nút submit trong form logon_form
if Request(“submit”) “” then
Application.lock
error = 0
numuser = Application(“count”)
if numuser >= Application(“MAXUSER”) then
error = 1 ‘chatroom đã đầy
else
if numuser > 0 then
for i = 0 to numuser – 1
if nick = Application(“users” & i) then
error = 2 ‘tên này đã có người dùng
exit for
end if
next
end if
end if

if error = 0 then
Application(“users” & numuser) = nick
Application(“count”) = numuser + 1
Session(“nick”) = nick

‘thêm câu chúc mừng user mới vào nội dung của chatroom
current_pointer = Application(“pointer”)
Application(“content” & current_pointer) = error_msg(0)
Application(“pointer”) = (current_pointer + 1) MOD Application(“CHATSIZE”)
Application.unlock

‘Chuyển user sang trang web có frame để chat
Response.Redirect “frames.html”
Response.End
else
Response.write error_msg(error)
Application.unlock
end if
end if

%>

Khi user ra khỏi phòng chat thì ta cần gọi file logoff để xóa tên user khỏi danh sách các user. Hơn nữa, ta cũng cần câu thông báo cho mọi người biết rằng user đó đã logoff. Lưu đoạn mã dưới đây vào file logoff.asp

<%

dim numuser
dim current_pointer

Application.lock
numuser = Application(“count”)

‘tìm vị trí của user này trong array chứa danh sách user
for i = 0 to numuser – 1
if Session(“nick”) = Application(“users” & i) then
index = i
exit for
end if
next

‘sau khi xóa user này xong, cần phải dồn array lại nếu đây không phải là user cuối cùng
if index < numuser – 1 then
for i = index to numuser – 2
Application(“users” & i) = Application(“users” & i + 1)
next
end if

‘thêm câu thông báo user mới vừa rời phòng chat
current_pointer = Application(“pointer”)
Application(“content” & current_pointer) = “—– ” & Session(“nick”) & “ vua roi chatroom —–”
Application(“pointer”) = (current_pointer + 1) MOD Application(“CHATSIZE”)

Application(“users” & numuser) = “”
Session(“nick”) = “”
Application(“count”) = numuser – 1
Application.unlock

Response.Redirect “index.asp”
Response.End

%>

Ta có thể đặt thêm nút nhấn trong file input.asp để user logoff như sau:













Tuy nhiên, nếu user không nhấn vào nút logoff mà đóng cửa sổ trình duyệt web lại thì sao? Để tránh trường hợp này, ta thêm đoạn mã javascript sau vào file frames.html:



ASP CHATROOM









Sorry, your browser does not support frames.



Đến đây, bạn có thể gộp các files trên lại và bỏ chung 1 vào thư mục nào đó và tạo 1 virtual folder trong IIS là có thể chạy được cái chatroom này rồi. Nhớ tạo ra 2 cái hình cười và mếu, bỏ vào thư mục con images!

No comments: