Đề tài Xây dhựng ứng dụng truyền thông âm thanh trên mạng cục bộ

Đồ án tốt nghiệp đã hoàn thành các nhiệm vụ đề ra trong phạm vi cho phép. Do điều kiện về thời gian cùng như trình độ còn hạn chế nên đồ án này dừng lại ở mức nghiên cứu một số phương pháp mã hoá tiếng nói và một số giao thức truyền tín hiệu trên mạng Internet như TCP/IP, UDP. Trên cơ sở đó xây dựng phần mềm thử nghiệm truyền tiếng nói thoại trên mạng LAN.

Đồ án này của em sử dụng các hàm có sẵn trong môi trường SDK từ đó xây dựng ứng dụng CPhone có thể liên kết hai máy lại và thực hiện quá trình trao đổi âm thanh.

Phần thử nghiệm mới chỉ dừng lại ở việc xây dựng một ứng dụng truyền tiếng nói giữa 2 thực thể PC theo giao thức TCP/IP và tiếng nói mới chỉ được mã hoá theo phương pháp PCM nên tỷ số nén và tốc độ truyền chưa cao. Mặt khác, do mới chỉ đánh giá được chất lượng tiếng nói theo phương pháp chủ quan nên chưa khảng định được điều gì về độ trễ và chất lượng tiếng nói sau khi truyền. Thế nhưng những gì đạt được trong đồ án này chủ yếu là nhằm giúp em có thể nắm bắt được vững hơn về mặt lý thuyết cũng như nắm quyền kiểm soát, quyền điều khiển ứng dụng trong thực tế, các kết quả này rất qua trọng và hữu ích cho mọi hoạt động nghiên cứu sau này cho dù những nội dung trong bài luận văn và phần thử nghiệm chưa được đầy đủ và hoàn chỉnh như mong muốn.

 

doc68 trang | Chia sẻ: huong.duong | Lượt xem: 1142 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Đề tài Xây dhựng ứng dụng truyền thông âm thanh trên mạng cục bộ, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
bị thực thi bằng các handles và Identifiers. IV.1.3 SỬ DỤNG CÁC THIẾT BỊ XUẤT NHẬP, HỖ TRỢ WAVEFORM AUDIO Chúng ta dùng hàm waveOutOpen để mở thiết bị đầu ra nhằm xuất dữ liệu dạng waveform. Hàm sẽ mở thiết bị waveOut và trả handle về cho ứng dụng. Hệ thống multimedia sẽ hỗ trợ nhiều dạng output dữ liệu khác nhau do đó khi mở thiết bị nếu cần chúng ta phải chỉ định rõ thông số dữ liệu. Ví dụ chúng ta dùng cờ WAVE_MAPPER để xác định thiết bị output sẽ xuất âm thanh dạng waveform. Dò tìm thiết bị Windows cung cấp các hàm sau giúp chúng ta xác định các thiết bị trong hệ thống phù hợp cho yêu cầu của mình. Hàm Chức năng AuxGetNumDevs Truy xuất số lượng các thiết bị sẵn có trong hệ thống WaveInGetNumDevs Truy xuất số lượng các thiết bị nhập hỗ trợ waveform audio sẵn có trong hệ thống WaveOutGetNumDevs Truy xuất số lượng các thiết bị xuất hỗ trợ waveform audio sẵn có trong hệ thống Các thiết bị khai báo trong hệ thống được đánh các chỉ số nhận dạng bắt đầu từ 0. Sau khi xác định số lượng các thiết bị sẵn có trong hệ thống, chúng ta có thể dò tìm khả năng của từng thiết bị bằng các hàm sau: Hàm Chức năng AuxGetDevCaps Truy xuất khả năng của thiết bị xuất WaveInGetDevCaps Truy xuất khả năng của thiết bị nhập dạng waveform WaveOutGetDevCaps Truy xuất khả năng của thiết bị xuất dạng waveform Các hàm truy xuất này sẽ truy xuất này sẽ lấy các cấu trúc liên quan đến khả năng của thiết bị. Các cấu trúc dưới đây sẽ tương ứng với các hàm liệt kê ở trên: Hàm Structure AuxGetDevCaps AUXCAPS WaveInGetDevCaps WAVEINCAPS WaveOutGetDevCaps WAVEOUTCAPS Thiết bị waveform có khả năng hỗ trợ các dạng format không chuẩn. Dạng format không chuẩn này được dùng trong cấu trúc WAVEFORMATEX. Handle và Identifier của thiết bị Khi mở thiết bị, chúng ta sẽ nhận được handle hay thông số Identify của thiết bị. Chúng ta sẽ điều khiển thiết bị qua các thông số này. Sự khác biệt giữa handle và identify là khó thấy nhưng rất quan trọng. Identitier của thiết bị được chỉ định ngầm định từ số lượng các thiết bị sẵn có trong hệ thống. Identifier sẽ được trả về khi chúng ta dùng các hàm auxGetNumDevs, waveInGetNumDevs, or waveOutGetNumDevs Hàm. Handle của thiết bị là thông số trả về của device driver khi chúng ta dùng các hàm waveInOpen hay waveOutOpen. Waveform-Audio Output Data Types Các thông số dưới đây được dùng cho thiết bị waveform output Cấu trúc Chức năng HWAVEOUT Handle của thiết bị waveform output WAVEFORMATEX Cấu trúc dùng chỉ định dạng format thiết bị output/ input WAVEHDR Cấu trúc dùng làm header cho khối dữ liệu waveform. Cấu trúc được dùng cho cả thiết bị output và input WAVEOUTCAPS Cấu trúc dò hỏi khả năng của thiết bị output. Chỉ định dạng format của dữ liệu waveform audio Khi chúng ta mở thiết bị output bằng hàm waveOutOpen, thông số pwfx sẽ chỉ định cấu trúc WAVEFORMATEX xác định dạng format của dữ liệu waveform. Đây là cấu trúc mở rông của cấu trúc WAVEFORMAT. Ghi dữ liệu waveform Sau khi mở thiết bị xuất, chúng ta có thể xuất dữ liệu bằng cách gọi hàm waveOutWrite. Hàm sẽ gửi khối dữ liệu âm thanh ra thiết bị xuất. Chúng ta dùng cấu trúc WAVEHDR để chỉ định header của khối dữ liệu được gửi ra. Header này gồm con trỏ tới khối dữ liệu đã lock, chiều dài khối dữ liệu và một số thông số cờ. Khối dữ liệu phải được prepare trước khi đem ra sử dụng. Sau khi gửi khối dữ liệu đến thiết bị output, chúng ta phải chờ driver hoàn tất việc xử lý khối dữ liệu trước khi giải phóng nó. Khi chúng ta cần gửi nhiều khối dữ liệu liên tục, chúng ta sẽ phải theo dõi việc xử lý hoàn tất khối dữ liệu để có thể gửi khối tiếp theo. PCM Waveform-Audio Data Format Thông số lpData trong cấu trúc WAVEHDR sẽ trỏ đến dữ liệu đã được lấy mẫu. Đối với dữ liệu PCM 8-bit, mỗi giá trị lấy mẫu được biểu diễn bằng một số 8 bit không dấu. Đối với dữ liệu PCM 16-bit, mỗi giá trị lấy mẫu được biểu diễn bằng một số 16 bit không dấu. Bảng dưới đây cho chúng ta thấy các giá trị cao nhất, thấp nhất cũng như giá trị trung bình của dữ liệu PCM: Data format Maximum value Minimum value Midpoint value 8-bit PCM 255(0xFF) 0 128 (0x80) 16-bit PCM 32,767 (0x7FFF) -32,768 (0x8000) 0 Các gói dữ liệu PCM Thứ tự của dữ liệu thay đổi tùy theo dạng format 8-bit hay 16-bit, stereo hay mono. Bảng dưới đây trình bày các gói dữ liệu của các dạng PCM khác nhau: PCM waveform Chức năng 8-bit mono Mỗi giá trị lấy mẫu là 1 byte tương ứng một kênh. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . . 8-bit stereo Mỗi giá trị lấy mẫu là 2 byte. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . . Với mỗi giá trị mẫu byte đầu là kênh 0 (trái) còn byte sau là kênh 1 (phải). 16-bit mono Mỗi giá trị lấy mẫu là 2 byte. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . . Với mỗi giá trị mẫu byte đầu là byte thấp của kênh 0 còn byte sau là byte cao của kênh 0. 16-bit stereo Mỗi giá trị lấy mẫu là 4 byte. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . . Với mỗi giá trị mẫu byte đầu là byte thấp của kênh 0 (trái), byte thứ 2 là byte cao của kênh 0, byte thứ 3 là byte thấp của kênh 1 (phải) còn byte thứ 4 là byte cao của kênh 1. Đóng thiết bị waveform-Audio Output Sau khi thực thi công việc xong, chúng ta sẽ gọi hàm waveOutClose để đóng thiết bị. Khi thiết bị đang thực thi mà gọi hàm này thì lỗi sẽ xảy ra. Nếu chúng ta muốn đóng thiết bị giữa chừng thì đầu tiên chúng ta nên gọi hàm waveOutReset trước khi đóng thiết bị. Nhưng trước đó cũng cần gọi hàm waveOutUnprepareHeader để unprepare tất cả các khối dữ liệu. Playing Waveform-Audio Files Chúng ta có thể dùng các hàm sau đây để xuất dữ liệu dạng âm thanh ra loa: Hàm Chức năng MessageBeep Xuất âm thanh dưới dạng thông báo của hệ thống SndPlaySound Xuất âm thanh dưới dạng đăng ký trước trong hệ thống hay là nội dung của một file wave PlaySound Giống như hàm trên và thêm cơ chế truy xuất trực tiếp tài nguyên. Các hàm PlaySound và sndPlaySound sẽ nạp hoàn toàn nội dung file wave vào bộ nhớ và xuất ra ngõ output. Khả năng bộ nhớ của chúng có giới hạn nên chúng chỉ quản lý được các nội dung dưới 100KB. Khi làm việc với các file có nội dung lớn hơn thì chúng ta có thể sử dụng các dịch vụ do MCI cung cấp. Sử dụng Windows message trong việc quản lý khi playback Các Thông báo dưới đây có thể được sử dụng trong quá trình xuất dữ liệu: Thông báo Chức năng MM_WOM_CLOSE Được gửi đi khi đóng thiết bị bằng hàm waveOutClose MM_WOM_DONE Được gửi đi sau khi driver hoàn tất việc xuất dữ liệu bằng hàm wafveOutWrite. MM_WOM_OPEN Được gửi đi khi thiết bị được mở bằng hàm waveOutOpen. Các thông số wParam và lParam cũng rất cần thiết. Thông số wParam luôn luôn xác định handle của thiết bị waveform-audio. Đối với thông số lParam, Thông báo MM_WOM_DONE dùng thông số này trỏ tới cấu trúc WAVEHDR chỉ định sụ hoàn tất của dữ liệu trong khi thông số này không được hai Thông báo còn lại dùng. Việc dùng này rất hữu hiệu, Thông báo MM_WOM_DONE sẽ là tín hiệu được báo về sau khi việc playback khối dữ liệu hoàn tất. Ta sẽ tiếp nhận Thông báo này và giải phóng các biến có liên quan. Thay đổi volume của quá trình playback dữ liệu waveform audio Chúng ta sẽ dùngcác hàm sau đây để lấy thông số volume cũng như thiết lập các thông số này theo yêu cầu. Hàm Chức năng WaveOutGetVolume Truy xuất mức volume của thiết bị xuất WaveOutSetVolume Thiết lập mức volume cho thiết bị Giá trị volume là một số doubleword. Khi audio format là stereo, 16 bit cao chỉ giá trị volume của channel phải và 16 bits thấp chỉ giá trị volume của channel trái. Còn nếu ở các thiết bị không hỗ trợ 2 kênh thì 16 bit thấp sẽ được sử dụng chỉ giá trị volume còn 16 bit cao sẽ không dùng đến. Giá trị volume thay đổi từ giá trị 0x0 (silence) cho đến mức 0xFFFF (maximum) Recording Waveform Audio Chúng ta có thể sử dụng dịch vụ thu âm thanh theo chuẩn MCI. Tuy nhiên nếu thấy cần thiết, chúng ta có thể sử dụng các hàm thu âm thanh cấp thấp. Các thông số dữ liệu dưới đây sẽ đặc trưng cho dạng dữ liệu waveform audio input Structure Chức năng HWAVEIN Handle của thiết bị input WAVEFORMATEX Cấu trúc của dạng dữ liệu được thiết bị input hỗ trợ WAVEHDR Cấu trúc dùng làm header của khối dữ liệu input. Nó cũng được dùng khi xuất dữ liệu ra Output WAVEINCAPS Cấu trúc dùng dò hỏi các khả năng của thiết bị input Trước khi bắt đầu công việc thu dữ liệu, chúng ta phải dùng hàm waveInGetDevCaps để dò hỏi khả năng cũng như xác định các thuôïc tính của thiết bị. Hàm sẽ trả về cấu trúc WAVEINCAPS xác định các thông số mong muốn. Opening Waveform-Audio Input Devices Để thu dữ liệu, trước hết chúng ta dùng hàm waveInOpen để mở thiết bị waveform input. Nếu thực thi thành công, hàm sẽ trả về cho chúng ta handle của thiết bị. Managing Waveform-Audio Recording Sau khi mở thiết bị, chúng ta có thể tiến hành việc thu dữ liệu. Dạng dữ liệu waveform thu được sẽ được đưa vào buffer, buffer này được trỏ đến trong cấu trúc WAVEHDR. Trước khi được sử dụng, chúng ta phải prepare buffer này. Windows cung cấp cho chúng ta các hàm sau đây dùng thu dữ liệu waveform: Hàm Chức năng WaveInAddBuffer Gửi một buffer cho device driver, thiết bị sẽ thu dữ liệu vào khối này WaveInReset Ngừng thu dữ liệu và đánh dấu tất cả các buffer đã thu xong WaveInStart Bắt đầu thu dữ liệu. WaveInStop Kết thúc việc thu dữ liệu Chúng ta dùng hàm waveInAddBuffer để gửi các khối buffer tới device driver. Khi dữ liệu được điền đầy vào buffer, ứng dụng sẽ được thông báo bằng window Thông báo, callback Thông báo, thread Thông báo, hay event, tùy theo cờ thông báo được chỉ định trong hàm open device. Trước khi bắt đầu thu dữ liệu, chúng ta phải gửi ít nhất một buffer dữ liệu cho thiết bị input và khi đóng thiết bị, chúng ta gọi hàm waveInReset để đánh dấu các buffer đã được thu xong. Using Window Messages to Manage Waveform-Audio Recording Các Thông báo sau đây sẽ được dùng để quản lý việc thu dữ liệu dạng waveform audio: Thông báo Chức năng MM_WIM_CLOSE Được gửi đi khi thiết bị đóng lại khi gọi hàm waveInClose MM_WIM_DATA Được gửi đi khi thiết bị thu đầy một buffer khi gọi hàm waveInAddBuffer MM_WIM_OPEN Được gửi đi khi thiết bị được open khi gọi hàm waveInOpen Thông số lParam của MM_WIM_DATA là pointer trỏ đến cấu trúc WAVEHDR để nhận dạng buffer dữ liệu. Buffer có thể không chứa đầy dữ liệu vì việc thu dữ liệu có thể kết thúc trước khi buffer được thu đầy. Chúng ta có thể biết được kích thước thật sự của dữ liệu bằng thông số dwBytesRecorded. Audio data block Hàm waveInAddBuffer và waveOutWrite có thông số yêu cầu ứng dụng chỉ định khối dữ liệu cần cho thiết bị sử dụng cho việc thu hay playback. Các hàm trên sử dụng cấu trúc WAVEHDR để miêu tả khối dữ liệu trên. Trước khi sử dụng các hàm trên để gửi khối dữ liệu cho thiết bị. Chúng ta phải cấp phát vùng nhớ cho khối dự liệu và khối header. Khối header phải được prepare và unprepare bằng các hàm sau: Hàm Chức năng WaveInPrepareHeader Prepare khối dữ liệu input WaveInUnprepareHeader Unprepare khối dữ liệu input WaveOutPrepareHeader Prepare khối dữ liệu output WaveOutUnprepareHeader Unprepare khối dữ liệu output Trước khi gửi khối dữ liệu cho driver input hay output, chúng ta phải prepare chúng. Sau khi thiết bị sử dụng xong, các khối dữ liệu phải được unprepare trước khi giải phóng các vùng nhớ đã cung cấp. Khi kích thước dữ liệu lớn, chúng ta phải cung cấp các buffer liên tục cho thiết bị, quá trình này phải diễn ra liên tục cho đến khi hoàn tất công việc và thiết bị được đóng lại. Ứng dụng phải xác định và quản lý thời điểm mà thiết bị hoàn tất việc thự thi trên các khối dữ liệu để đưa ra các tác động thích hợp. Các cách sau đây được đưa ra: Chiû định hàm callback nhận Thông báo mà thiết bị gửi khi nó hoàn tất một khối dữ liệu. Sử dụng các event callback Chỉ định window hay thread nhận Thông báo gửi từ thiết bị. Xác định bit WHDR_DONE trong cờ dwFlags của cấu trúc WAVEHDR đi kèm với mỗi khối dữ liệu. Khi ứng dụng không đáp ứng được tốc độ xử lý các buffer thì chiến lược buffer kép có thể được đưa ra để tăng tốc độ thực thi. Chúng ta sẽ khảo sát một số phương thức xử lý sau khi thiết bị hoàn tất một khối dữ liệu. Dùng hàm callback để xử lý các driver messages Để chỉ định hàm callback xử lý ứng vớicác driver message, chúng tachỉ định cờ CALLBACK_FUNCTION trong biến fdwOpen và địa chỉ hàm xử lý trong biến dwCallback khi gọi hàm waveInOpen hay waveOutOpen. Messages gửi cho hàm callback tương tự như Thông báo gửi cho window, ngoại trừ việc nó có hai thông số DWORD thay vì một thông số DWORD và một thông số UINT. Để gửi dữ liệu cho hàm callback chúng ta có thể dùng một trong hai cách sau: Dùng thông số dwInstance trong hàm open device Dùng field dwUser trong cấu trúc WAVEHDR để chỉ định khối dữ liệu gửi cho device driver. Dùng event callback xử lý các driver message Để dung event callback, chúng ta dùng hàm CreateEventđể truy xuất handle của event. Trong hàm open thiết bị, chỉ định cờ CALLBACK_EVENT cho thông số fdwOpen. Sau khi gọi hàm waveOutPrepareHeader nhưng trước khi gửi dữ liệu cho thiết bị, chúng ta tạo ra một nonsignal event bằng cách gọi hàm ResetEvent, chỉ định event handle được lấy từ hàm CreateEvent. Trong vòng loop để kiểm tra khi bit WHDR_DONE được set trong cấu trúc WAVEHDR, chúng ta gọi hàm WaitForSingleObject, chỉ định thông số event handle và giá trị time-out là INFINITE. Giá trị event callback là giá trị dùng gọi hàm callback. Bởi vì event callback không xác định được thông báo xác định close, done hay open. Ứng dụng phải kiểm tra tình trạng của hệ thống đang chờ sự kiện gì xảy ra để đưa ra các đáp ứng chính xác. Dùng window hay thread để xử lý các message driver Để dùng hàm window callback, chúng ta chỉ định thông số CALLBACK_ WINDOW trong biến fdwOpen và chỉ định handle của window trong thông số dwCallback khi gọi hàm open thiết bị. Driver message sẽ được gửi tới window procedure. Tương tự như vậy, chúngta sẽchỉ định thông số CALLBACK_THREAD và thread handle trong hàm open khi chúng ta muốn thread xử lý các driver message. Ngoài cách thức dùng hàm callback, chúng ta có thể dựa vào thông số dwFlags trong WAVEHDR để xác định xem thiết bị có hoàn tất việc xử lý khối dữ liệu hay chưa. Các hàm kiểm tra lỗi Các hàm waveform audio sẽ trả về giá trị khác 0 khi có lỗi xảy ra. Windows cung cấp cho chúng ta các hàm xác định lỗi dựa trên các thông số này. Ứng dụng sẽ dựa vào các thông số xác định lỗi để quyết định công việc thực thi tiếp tục. Các hàm sau được dùng để xác định các lỗi xảy ra: Hàm Chức năng WaveInGetErrorText Trả về chuỗi text xác định lỗi xảy ra của input device WaveOutGetErrorText Trả về chuỗi text xác định lỗi xảy ra của output device IV.2 KỸ THUẬT TRUYỀN NHẬN ÂM THANH TRÊN MẠNG IP IV.2.1 MÔ HÌNH LIÊN KẾT VÀ TRAO ĐỔI DỮ LIỆU Chương trình dùng giao thức TCP/IP làm giao thức giao tiếp. Việc thiết lập liên kết cũng như trao đổi dữ liệu đều tuân theo các cấp của giao thức này. Việc gọi và thiết lập liên kết được thực hiện theo mô hình client/server, việc trao đổi dữ liệu được thực hiện thông qua socket theo giao thức TCP. Có hai ý tưởng được đưa ra trong việc dùng socket để trao đổi dữ liệu. Dùng 1 socket : Mỗi máy dùng một socket để truyền nhận dữ liệu. Theo giao thức TCP sau khi hai socket connect được với nhau thì việc tiến hành trao đổi dữ liệu sẽ bắt đầu. Chúng ta sẽ dùng cặp socket này. Như vậy, một socket trên một máy đồng thời đảm nhận việc truyền dữ liệu đi cũng như nhận dữ liệu về.[3] socket socket Yêu cầu truyền dữ liệu Yêu cầu nhận dữ liệu socket Hình IV.1 Mô hình dùng 1 socket Cách dùng này có đặc điểm là việc tạo liên kết đơn giản, quá trình tạo liên kết hoàn toàn giống như các bước trong việc tạo liên kết giữa các socket dùng giao thức TCP. Chương trình chạy và lắng nghe ở một port xác định. Khi có một yêu cầu gọi liên kết đến, chương trình sẽ tạo ra một socket để nối kết với socket gọi. Sau khi thiết lập liên kết thì các socket bắt đầu gửi nhận dữ liệu. Socket sẽ gửi dữ liệu âm thanh đi đồng thời nhận dữ liệu truyền tới và chuyển cho hệ thống xử lý. Socket làm việc theo cách này sẽ nhận hai thông báo cùng một lúc. Khi có dữ liệu từ mạng truyền tới, hệ thống sẽ thông báo cho socket để tiến hành việc nhận dữ liệu. Cũng tương tự như vậy, khi có dữ liệu âm thanh sẵn sàng, hệ thống cũng sẽ gọi socket để truyền đi. Như vậy, khi thực thi socket sẽ nhận được hai thông báo của hệ thống. Vì việc truyền nhận dữ liệu âm thanh là dạng dữ liệu liên tục cho nên tần suất mà hệ thống thông báo cho socket là rất thường xuyên. Vì vậy, socket trong cùng một lúc có thể nhận được cả hai yêu cầu truyền dữ liệu đi và nhận dữ liệu về. Thêm vào đó các hoạt động truyền nhận dữ liệu là các hoạt động bị tắc nghẽn. Do đó chúng ta phải lưu ý đến hiện tượng này, socket có thể đáp ứng không kịp nhu cầu của hệ thống. Chúng ta lấy một trường hợp ví dụ. Khi socket nhận được yêu cầu truyền dữ liệu đi, nó sẽ lấy dữ liệu từ các buffer và truyền đi. Do quá trình truyền dữ liệu có thể bị tắc nghẽn, socket sẽ phải chờ. Đồng thời trong lúc này, nó lại nhận được tín hiệu thông báo có buffer kế tiếp cần truyền đi và tín hiệu thông báo có dữ liệu trên mạng truyền về. Với các yêu cầu dồn dập như vậy, hệ thống có thể sẽ đáp ứng không kịp và chương trình có thể bị treo. Vì vậy, khi dùng một socket để truyền nhận dữ liệu, chúng ta phải tính toán cân đối thời gian giữa việc truyền dữ liệu đi và việc nhận dữ liệu về sao cho hợp lý để hệ thống có thể làm việc liên tục được. Chúng ta có thể qui định thời gian cho việc truyền nhận. Trong một thời điểm socket có thể chỉ làm việc truyền dữ liệu đi, các yêu cầu nhận dữ liệu sẽ bị ngưng lại. Sau đó socket sẽ chỉ xử lý các yêu cầu nhận dữ liệu. Chiến lược này giúp giảm nhẹ hoạt động của socket. Tuy nhiên, chúng ta cần áp dụng cho cả hai socket liên kết. Trong một thời điểm, một socket sẽ truyền còn socket còn lại sẽ nhận dữ liệu, và thời điểm sau thì quá trình sẽ diễn ra theo chiều ngược lại. Dùng 2 socket : Xuất phát từ ý tưởng trên, chúng ta có thể dùng hai socket trong việc trao đổi dữ liệu. Một liên kết hình thành giữa hai máy sẽ gồm hai cặp socket liên kết với nhau. Một socket chỉ đảm nhận việc truyền dữ liệu trong khi socket còn lại đảm nhận việc nhận dữ liệu.[3] Socket truyền Socket truyền Socket nhận Socket nhận Yêu cầu truyền dữ liệu Yêu cầu nhận dữ liệu Socket truyền Socket nhận Hình IV.2 Mô hình dùng 2 socket Vì mỗi socket chỉ nhận một tín hiệu nhất định. Socket truyền sẽ chỉ chú ý tới tín hiệu báo có dữ liệu của hệ thống để tiến hành truyền dữ liệu đi. Trong khi đó, socket nhận sẽ chỉ lưu ý đến tín hiệu báo có dữ liệu của hệ thống. Hai socket sẽ hoạt động độc lập với nhau và công việc của một socket sẽ nhẹ nhàng hơn mô hình trên. Tuy nhiên, trong mô hình này, việc thiết lập liên kết giữa hai máy sẽ trở nên phức tạp hơn. Theo mô hình client/server, khi một socket gọi và thiết lập liên kết với chương trình ở máy remote xong thì máy remote cũng phải tạo ra một socket và tiến hành liên kết ngược lại. Sau khi cặp socket hoàn toàn liên kết xong thì hai máy mới coi như đã connect và tiến hành truyền nhận dữ liệu. Một khía cạnh khác cần lưu ý là tuy hai socket hoạt động độc lập với nhau nhưng chúng đều thuộc cùng một chương trình và chúng đều tiến hành việc gửi nhận dựa trên các giao thức lớp dưới chung. Do đó, trong một thời điểm chỉ có một hoạt động diễn ra hoặc là truyền dữ liệu hoặc là nhận dữ liệu. Vì vậy thật ra hai socket cũng phải hoạt động phụ thuộc nhau. Socket gửi dữ liệu phải chờ socket nhận nhận xong dữ liệu rồi mới bắt đầu truyền đi và ngược lại việc truyền dữ liệu phải được hoàn tất thì việc nhận dữ liệu mới có thể tiến hành được. Một vấn đề khác nẩy sinh do đặc điểm của dữ liệu. Dữ liệu tiếp nhận là dạng dữ liệu liên tục do đó, các tín hiệu mà hệ thống báo cho hai socket cũng xảy ra liên tục, vì vậy thực sự rằng tuy chỉ làm một công việc nhưng khối lượng công việc mà socket phải đảm nhận là rất lớn. Thêm vào đó, hai socket đều phụ thuộc vào một process do đó thật sự xét về mặt thực thi của quá trình thì khả năng giảm nhẹ công việc là không bao nhiêu. Và khả năng hệ thống bị treo do quá tải cũng vẫn có thể xảy ra. Chúng ta có những cách giải quyết để giảm nhẹ việc thực thi của chương trình như dùng cơ chế xử lý song song (thread) hay dùng cơ chế phân chia thời gian cho các hoạt động như đã nói ở trên. IV.2.2 CƠ CHẾ GỌI VÀ XÁC LẬP LIÊN KẾT Khi liên kết được xác lập, chúng ta sẽ bắt đầu tiến hành trao đổi dữ liệu. Tuy nhiên trước hết chúng ta cần khảo sát phương pháp gọi cũng như thiết lập liên kết. Chương trình được hiện thực dựa trên cơ chế client/server cho nên việc tạo liên kết cũng dựa trên cơ chế này. Ý tưởng chính là: khi chương trình bắt đầu thực thi, nó cũng bắt đầu lắng nghe lời gọi liên kết ở một port xác định. Thực sự, trong chương trình chúng ta sẽ tạo ra một socket server và lắng nghe ở một port qui ước trước. Khi một socket khác muốn tạo liên kết, nó sẽ tiến hành gọi liên kết với socket server ở giá trị port này.[3] Trong giao thức TCP/IP, một quá trình giao tiếp thông qua môi trường mạng phải có một chỉ số port xác định. Các quá trình khác nhau phải có port khác nhau. Khi thiết kế mô hình client/server, các nhà thiết kế đã tạo ra một số dịch vụ thông dụng trên mạng như: finger, echo, mail, ftp . . . Các server của các dịch vụ này được dành sẵn các port xác định mà không một quá trình nào được phép sử dụng. Các port này được gọi là well-known port và do hệ thống cấp phát và quản lý. Thông thường, các chỉ số well-known port có giá trị từ 0 đến 1023. Các ứng dụng không được phép sử dụng giá trị port trong khoảng này. Ứng dụng có thể dùng các giá trị port từ 1024 trở đi. Ví dụ: khi chúng ta cần tạo một socket mà không cần quan tâm đến giá trị port, chúng ta có thể nhờ hệ thống cấp cho một giá trị port còn trống. Thông thường các giá trị port mà hệ thông cung cấp cho ứng dụng khi có yêu cầu nằm trong khoảng từ 1024 đến 5000. Còn khi chúng ta muốn chỉ định một giá trị port cho socket, chúng ta sẽ có thể chọn giá trị từ 5000 trở đi. Vì trong vùng này xác suất mà port đó đã bị chiếm là rất hiếm. Vì vậy, khi thiết kế chúng ta muốn tạo một

Các file đính kèm theo tài liệu này:

  • docLV0923.doc
Tài liệu liên quan