Thứ Tư, 6 tháng 8, 2014

[JAIN SIP] Chương 6: Thực hành JAIN SIP

Phần 7: Thực hành JAIN SIP
I. Cấu trúc của chương trình :
- Bước 1: tạo ra class exampleListener kế thừa SipListener interface để xử lý các sự kiện trong quá trình thực hiện trao đổi SIP.  
p7_table_exampleListener.png
- Bước 2: định nghĩa SipProvider (SipProvider là trọng tâm của quá trình thực hiện SIP), để tạo ra SipProvider trước tiên phải định nghĩa SipFactory, SipStack, SipListeningPoint.
Lưu ý: chạy chương trình sip thì cần 2 máy tính khác nhau, nếu thực hành trên cùng 1 máy tính thì port phải khác nhau. Chương trình này chúng tôi chạy trên 1 máy tính nên port phải khác nhau.
- Bước 3: định nghĩa HeaderFactory, AddressFactory, MessageFactory
p7_table_defineHAMFactory.png
Code đầy đủ :
II. Tạo Sip Message:
Giả sử bạn muốn tạo 1 sip message như sau:
Trong Jain SIP:
III. Xây dựng  giao diện biễu diễn SIP:
Chúng ta sẽ bắt đầu xây dựng 1 giao diện như trên:
- Vì chạy chương trình trên cùng 1 máy nên port phải khác nhau, bấm vào button “bắt đầu” để khởi động SIP.
- Button “Gởi” sẽ gởi đi 1 REGISTER request  dựa trên địa chỉ AOR và địa chỉ UAS.
- 1 TextArea được sử dụng để hiển thị SIP Message.
1. Cấu trúc chương trình:
Chúng ta sẽ tạo ra 1 class exampleGUI để biểu diễn màn hình như trên. Như vậy, chúng ta có 2 class: exampleListener và exampleGUI
a. exampleGUI class:
Các biến cần thiết của class exampleGUI:
Các phương thức của class exampleGUI :
- Phương thức getPort(), getAOR(), getUAS() trả về giá trị Port, địa chỉ AOR, địa chỉ UAS do người dùng nhập vào.
- Phương thức DisplayMessage() để hiển thị sip message trong txtHIENTHI
p7_table_2_displayMessageGUI.png
- Phương thức setBATDAU() để hiện thị địa chỉ IP,Port của user và thông báo SIP đã được bắt đầu.
p7_table_2_setBATDAU.png
- Phương thức cmdBATDAUActionPerformed() sự kiện khi nhấn button “Bắt đầu”.
- Phương thức cmdGOIActionPerformed () sự kiện khi nhấn button “Gởi”.
b. exampleListener class:
- Bổ sung thêm đối tượng GUI vào class exampleGUI để lấy những thông tin do người dùng nhập vào, cũng như các sự kiện khi click button.
- Hàm dựng được bổ sung thêm tham số exampleGUI
- Phương thức sendMessage() được dùng để tạo 1 SIP Request REGISTER và gởi nó đến địa chỉ UAS .
2. Chạy chương trình:
Mỗi giao diện tương ứng 1 máy tính, nếu chạy trên cùng 1 máy tính port phải khác nhau.
Giả sử giao diện 1 :
- Sử dụng port 6060, bấm vào button “Bắt đầu” để khởi động SIP.
-  Địa chỉ AOR, tùy ý bạn đặt tên.
- Địa chỉ UAS phải chính xác là địa chỉ IP và Port của máy cần gởi đến.
- Bấm button “Gởi”.
 Giao diện 2 :
- Sử dụng port 6070, bấm vào button “Bắt đầu” để khởi động SIP.
- Địa chỉ AOR, tùy ý bạn đặt tên.
- Địa chỉ UAC phải chính xác là địa chỉ IP và Port của máy cần gởi đến.
- Bấm button “Gởi”.
Code đầy đủ của ví dụ III : exampleBasic.rar
IV.  Sử dụng Transaction layer:
Giống như chương trình ở phần III, nhưng trong phần III chỉ dừng lại ở mức UAC gởi và UAS nhận request, trong phần IV này chúng ta sẽ bổ sung thêm tính năng khi server nhận 1 request , server sẽ phản hồi lại “200 Ok Response”.
1. Cấu trúc chương trình:
Tương tự như trong phần III, vẫn giữ nguyên 2 class exampleListener và exampleGUI. Class exampleGUI giữ nguyên hoàn toàn, còn class exampleListener bổ sung thêm 1 số code trong các phương thức sau:  
a.  Phương thức sendMessage() :  
- Các bạn đã biết qua, UAS gởi 1 response đến client theo đúng con đường mà UAC gởi request đến server và quá trình này được lưu lại trong ViaHeader. Chương trình của chúng ta gởi trực tiếp từ UAC đến UAS, do đó Via Header chỉ lưu lại địa chỉ của UAC gởi Request. Giá trị tag của Via Header là null, thì JAIN SIP tự tạo giá trị tag cho Via Header.
- Khi gởi request, chúng ta không gởi trực tiếp qua SipProvider, mà thông qua đối tượng ClientTransaction được tạo ra từ SipProvider. ClientTransaction của transaction layer được sử dụng ở phía UAC dùng để gởi 1 request đến UAS và có nhiệm vụ so khớp các response được gởi trả về từ UAS, cũng như bắt các event diễn ra trong SipListener ở phía UAC.
Do đó, ở phương thức sendMessage(), chúng ta bổ sung sau:
b. Phương thức processRequest():
Phương thức này xử lý quá trình khi UAS nhận 1 request, nên trong phương thức này khi nhận được request, UAS sẽ tự tạo ra 1 response “200 OK” gởi trả về UAC. Chúng ta thực hiện như sau:
- Tạo response “200 OK”:
- Tạo đối tượng ServerTransaction từ SipProvider để gởi response. ServerTransaction của transaction layer được sử dụng ớ phía UAS dùng để gởi các response đến UAC. Nhiệm vụ của ServerTransaction gởi các response phù hợp với request và bắt các event diễn ra trong SipListener ở phía UAS.
- Ở phương thức processRequest(), chúng ta bổ sung sau :
c.  Phương thức processResponse() :
Phương thức này xử lý quá trình khi client nhận được 1 response, nên trong phương thức này chúng ta lấy nội dung response được gởi từ UAS và hiển thị trong txtHIENTHI.
2.  Chạy chương trình:
Tương tự như trong phần III, chúng ta đánh dấu máy tính nào nhận message thì có chữ “nhận” trước message , máy tính nào gởi message thì có chữ “gởi” trước message.
Lưu ý : máy nhận request và gởi response là UAS. Còn máy gởi request và nhận response là UAC.
Code đầy đủ của ví dụ IV : exampleBasic1.rar
V. Tạo Dialog:
Trong phần V này chúng ta sẽ tạo một Dialog khi UAC gởi 1 INVITE request đến UAS. Khi vừa nhận được INVITE, UAS sẽ tự gởi phản hồi “180 Ringing” response đến UAC, và nếu UAS chấp nhận cuộc gọi thì “200 OK” response gởi đến UAC, đồng thời UAC cũng gởi 1 ACK request đến UAS.
  
  
Trong phần giao diện, chúng ta bổ sung thêm các tính năng sau:
- Button ”Gởi” được sử dụng khi người dùng phía UAC bấm vào button “Gởi” để tạo một INVITE request và gởi đến UAS.
- Button “Nhận” được sử dụng khi người dùng phía UAS chấp nhận cuộc gọi và 1 “200 OK" response  được tạo ra và gởi đến UAC.
- Label trạng thái được sử dụng để hiển thị trạng thái của Dialog.
 - Cấu trúc chương trình: vẫn giữ nguyên 2 class (exampleGUI,exampleListener) trong phần ví dụ IV và thay đổi như sau:
1. class exampleGUI:
- Bổ sung thêm label lblTRANGTHAI để hiển thị trạng thái của Dialog.
- Button cmdNHAN để thể hiện hành động chấp nhận cuộc gọi của Server.
- Phương thức setTRANGTHAI() gán giá trị trạng thái cho lblTRANGTHAI.
- Phương thức  cmdGOIActionPerformed() xử lý sự kiện khi bấm button “Gởi”.
- Phương thức  cmdNHANActionPerformed() xử lý sự kiện khi bấm button “Nhận”.
2. class exampleListener:
a. Biến toàn cục :  bổ sung các biến sau :
+ Trong Jain Sip, khi gởi đi 1 sip message bắt buộc phải bổ sung Contact Header vào sip message đó (trừ REGISTER request). Ý nghĩa của Contact Header là chứa địa chỉ, để gởi trực tiếp  các sip message tương lai. Trong ví dụ của chúng ta, tránh trường hợp tạo lại, chúng ta tạo đối tượng ContactHeader 1 lần trong hàm dựng và là biến toàn cục.
+  ClientTransaction được UAC sử dụng để gởi các message request đến UAS.
+  ServerTransaction được UAS sử dụng để gởi Response đến UAC.
b. Phương thức: loại bỏ phương thức sendMessage(), và thêm vào 2 phương thức khác là : sendRequest() và sendResponse().
- Phương thức sendRequest() : khi người dùng phía UAC nhấn vào button "GỞI" sẽ gọi phương thức này. Phương thức này tạo ra gởi 1 INVITE request và gởi đến UAS.
Những phần in đậm trong code bên trên là những phần bạn cần lưu ý:
+ Giá trị To header trong INVITE là địa chỉ UAS.
+ Kiểu request của CSeq header là "INVITE".
+ Kiểu request trong phương thức tạo createRequest() là "INVITE", để cho biết đây là INVITE request.
+ Thêm Contact header vào request.
+ Phương thức getState() của đối tượng ClientTransaction cho biết trạng thái hiện tại của 1 Dialog.
- Phương thức sendResponse () : khi người dùng phía UAS nhấn vào button "NHẬN" sẽ gọi phương thức này. Phương thức này tạo ra "200 OK" response và gởi đến UAC.
Những phần in đậm trong code bên trên là những phần bạn cần lưu ý:
+  Phương thức getRequest() của đối tượng ServerTransaction. Đối tượng ServerTransaction đã được khởi tạo trong phương thức processRequest() của SipListener khi UAS vừa nhận được INVITE request. Và phương thức getRequest() trả về đối tượng Request mà ServerTransaction đang lưu giữ.
Lưu ý : 1 Dialog chỉ tồn tại duy nhất 1 ClientTransaction và 1 ServerTransaction.
+ Thêm Contact header vào response.
+ Phương thức getState() của đối tượng ServerTransaction cho biết trạng thái hiện tại của 1 Dialog.
- Phương thức processRequest() : của SipListener sử dụng ở phía UAS, bắt event khi UAS nhận request. Trong phương thức này, chúng ta sẽ tạo ra "180 Ringing" response gởi đến UAC khi UAS nhận được request, nhằm ngụ ý thông báo với UAC rằng "UAS đã nhận được request và đang chờ đợi người dùng chấp nhận".
Những phần in đậm trong code bên trên là những phần bạn cần lưu ý:
+  Phương thức getMethod() của đối tượng request trả về kiểu phương thức của request.
+ Đối với response đầu tiên gởi đến UAC, phải bổ sung giá trị tab cho To header.
+ Khởi tạo đối tượng serverTransaction. Lưu ý: cùng 1 dialog đối tượng này chỉ được khởi tạo 1 lần duy nhất.
- Phương thức processResponse() : của SipListener sử dụng ở phía UAC, bắt event khi UAC nhận được Response. Trong phương thức này, chúng ta tạo ra 1 ACK request gởi đến UAS để kết thúc dialog.
Những phần in đậm trong code bên trên là những phần bạn cần lưu ý:
+  Phương thức getStatusCode() của đối tượng response trả về giá trị Status Code của response.
+ Sử dụng phương thức createAck() của đối tượng clientTransaction để tạo ra ACK request.
+  Để gởi ACK request, chúng ta sử dụng Dialog đang tồn tại để gởi. Phương thức getDialog() của đối tượng ClientTransaction trả về Dialog đang tồn tại phía UAC. Còn phương thức getDialog() của đối tượng ServerTransaction trả về Dialog đang tồn tại phía UAS.

2. Thứ tự thực hiện các phương thức trong exampleListener của UAC và UAS :
Hình trên thứ tự sử dụng các phương thức của UAC và UAS. Phía UAC thì không sử dụng phương thức processRequest() và sendResponse(), ngược lại phía UAS thì không sử dụng phương thức sendRequest() và processResponse().
3. Chạy chương trình:
Tương tự như trong phần ví dụ IV, chúng ta đánh dấu UA nào nhận message thì có chữ “nhận” trước message, UA nào gởi  thì có chữ “gởi” trước message.
Code đầy đủ của ví dụ V : exampleBasic2.rar
VI. Kết thúc một Dilog bằng cách gởi BYE Request:
Trong ví dụ phần V, UAC bắt đầu cuộc gọi bởi nhấn button “Gởi” và chờ UAS trả lời bởi nhấn button “Nhận” để kết thúc cuộc gọi. Trong phần VI này , chúng ta bổ sung thêm tính năng : UAC bắt đầu cuộc gọi và được quyền kết thúc cuộc gọi. Để làm được điều này UAC phải gởi BYE Request đến Server.
Trong phần giao diện, chúng ta bổ sung thêm button “Kết thúc” để UAC bấm vào để kết thúc cuộc gọi.
Cấu trúc chương trình: Vẫn giữ nguyên 2 class trong phần ví dụ  V và bổ sung thêm tính năng vào 2 class này.
1. class exampleGUI:
- Bổ sung thêm button KETTHUC.
- Phương thức cmdGOIActionPerformed() xử lý sự kiện khi UAC bấm button "Gởi".
- Phương thức cmdKETTHUCActionPerformed() xử lý sự kiện khi client bấm button KETTHUC
2. class exampleListener:
- Mỗi ClientTransaction và ServerTransaction đại diện cho một 1 Transaction (bạn xem lại transaction trong chương 3) gởi 1 Request và các Response phản hồi. Do đó, trong ví dụ chúng ta tạo ra 2 ClientTransaction và 2 ServerTransaction:
+ ClientTransaction và ServerTransaction đại diện cho INVITE Request.
+ ClientTransaction  và ServerTransaction đại diện cho BYE Request.
Lưu ý:  Mỗi clientTransaction và ServerTransaction chỉ khởi tạo 1 lần duy nhất nên chúng ta đều đặt nó làm biến toàn cục.
- Phương thức sendRequest() : bổ sung thêm tham số đầu vào kiểu String cho biết kiểu request sẽ được tạo và gởi đến UAS.
Những phần in đậm trong code bên trên là những phần bạn cần lưu ý:
+  Hằng số Request.INVITE hoặc  Requset.BYE của đối tượng Request, là kiểu String chứa giá trị kiểu request. Bạn có thể sử dụng giá trị chuỗi "INVITE" hoặc "BYE" thay thế các hằng số này hoặc ngược lại.
+ Phương thức createRequest() của đối tượng Dialog, được sử dụng để tạo ra 1 BYE request mới cùng dialog với INVITE request trước đó. Nếu bạn tạo BYE request mới bằng phương thức createRequest() của đối tượng MessageFactory, thì BYE request này không cùng dialog với INVITE request trước đó.
+ Tạo ra 1 Transaction mới để gởi BYE request. Lưu ý: Tất cả các request đều có 1 transaction riêng, ngoại trừ ACK request.
- Phương thức processRequest()  : bổ sung thêm tính năng khi UAS nhận được là BYE request thì  tạo “200 OK” response gởi đến UAC và kết thúc cuộc gọi.
- Phương thức processResponse(): phía UAS có 2 trường hợp gởi 200 OK response:
+ Khi UAS nhận được BYE request.
+ Khi người dùng phía UAS bấm button "Nhận" phản hồi INVITE request.
Do đó, để phân biệt 200 OK response của 2 trường hợp này, chúng ta sử dụng CSeq header được dính kèm theo các response này.
2. Thứ tự thực hiện các phương thức trong exampleListener của UAC và UAS :
3. Chạy chương trình:
Tương tự như phần V:
Code đầy đủ của ví dụ VI :
http://www.mediafire.com/download/6qhw3hrhqxxkr6i/exampleBasic3.rar

Không có nhận xét nào:

Đăng nhận xét