Hoạt động của Radius Server và WebAdmin trên WAN đơn giản - Chương 2 ppsx

16 308 0
Hoạt động của Radius Server và WebAdmin trên WAN đơn giản - Chương 2 ppsx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

10 Chương II GIỚI THIỆU CÁC KỸ NĂNG BỔ TRỢ TRONG VIỆC PHÁT TRIỂN MÃ NGUỒN I-Giao diện Sockets (The Sockets Interface) Sockets được giới thiệu lần đầu tiên vào năm 1981 như là một phần của hệ thống phân phối phần mềm Berkeley 4.2 và được dùng như một giao diện cho một ứng dụng nền quan trọng. Hiện giờ, sockets đã được đặt vào UNIX System phiên bản V như là một phần của sự hợp nhất BSD/System V. Socket thực ra là một khối xây dựng cơ bản (basic building block) cho việc giao tiếp (communication). Socket là một đầu cuối (endpoint) của giao tiếp và có thể được gắn cho một cái tên (bound). Mỗi socket đang sử dụng có một kiểu (type) và có một hay nhiều process liên kết. Các sockets tồn tại trong các vùng giao tiếp (communication domains). Vùng giao tiếp là sự trừu tượng hóa bao hàm cả một cấu trúc đòa chỉ hay họ đòa chỉ (addressing structure – address family) và một tập các giao thức (protocols) thực hiện các kiểu sockets nằm trong vùng đó hay còn gọi là họ giao thức (protocol family). Communication domains được đưa ra nhằm chứa đựng các thuộc tính chung của các quá trình giao tiếp thông qua sockets. Một thuộc tính như vậy là sơ đồ được dùng cho tên sockets. Chẳng hạn, trong UNIX domain, sockets được đặt tên là tên đường dẫn trong UNIX. Ví dụ, một socket có thể có tên là /dev/foo. Các sockets thông thường chỉ trao đổi dữ liệu với các sockets trong cùng một domain (cũng có thể trao đổi giữa các sockets khác domains, nhưng phải cần có các quá trình dòch.). Giao diện socket của hệ thống UNIX cung cấp nhiều vùng giao tiếp độc lập: ví dụ như UNIX domain cho các giao tiếp trên cùng hệ thống (on-system communication); Internet domain 11 được dùng bởi các process giao tiếp sử dụng giao thức giao tiếp chẩn DARPA. Các công cụ giao tiếp nền tảng được cung cấp bởi các domains đã có sự tác động rất lớn trong việc thực thi các hệ thống bên trong (internal system) cũng như giao diện socket cung cấp cho user. 1-Kiểu Socket (Socket Types) Sockets có các kiểu phản ảnh các thuộc tính giao tiếp cho phép đối với user. Các quá trình được coi là chỉ giao tiếp giữa những sockets cùng kiều, mặc dù không có gì ngăn cản sự giao tiếp giữa các sockets thuộc các kiểu khác nhau. Có nhiều kiểu sockets hiện hành: a-Stream socket: Stream socket cung cấp cho luồng dữ liệu 2 chiều (bidirectional), đáng tin cậy (reliable), có thứ tự (sequenced) và không lập lại (unduplicated). Luồng dữ liệu này không có biên giới giữa các records. Một cặp stream sockets được nối với nhau cung cấp một giao diện giống hệt giao diện của pipes. b-Datagram socket: Datagramsocket cung cấp một luồng dữ liệu 2 chiều nhưng không đảm bảo có thứ tự, tin cậy và có thể lặp lại. Nghóa là, một process nhận message trên một datagram socket có thể tìm thấy message đó trên hai lần và có thể có thứ tự khác với thứ tự mà nó đã được gởi đi. Một đặc trưng quan trọng của datagram socket là biên giới giữa các records trong dữ liệu gởi được bảo toàn. Datagram socket có mô hình rất gần gũi với các tiện ích trong các mạng chuyển mạch gói hiện thời (packet switched networks) như Ethernet. c-Raw socket: Raw socket cung cấp sự truy xuất vào các giao thức giao tiếp nền có hổ trợ socket. 12 Những socket này thường là datagram oriented mặc dù tính chất chính xác của chúng phụ thuộc vào giao diện được cung cấp bởi protocol. Raw socket không có ý đònh trang bò chung cho các user mà chỉ dành cho các user muốn phát triển các giao thức giao tiếp mới hoặc muốn truy xuất sâu thêm vào các tiện ích bí mật (esoteric facilities) của giao thức đã có. 2-Tạo socket: Sử dụng lời gọi hệ thống socket() để tạo một socket. S= socket( domain, type, protocol); Lời gọi trên sẽ yêu cầu hệ thống tạo ra một socket trong một domain chỉ đònh và có kiểu chỉ đònh. Nếu protocol vẫn không được xác đònh (giá trò 0) thì hệ thống sẽ chọn một protocol thích hợp mà có thể chứa đựng domain đã cho và hổ trợ cho kiểu socket được yêu cầu. Một descriptor (một số nguyên nhỏ) được dùng sau lời gọi hệ thống như là một số hiệu để thực hiện các thao tác trên socket đã tạo ra. Các domains được đònh nghóa như những hằng số trong file <sys/socket.h>. Ví dụ, UNIX domain là AF_UNIX, Internet domain là AF_INET. Các kiểu của socket cũng được đònh nghóa trong file <sys/socket.h>. Ví dụ, stream socket là SOCK_STREAM, datagram socket là SOCK_DGRAM, raw socket là SOCK_RAW. Để tạo một socket stream trong Internet domain ta có thể gọi: S = socket (AF_INET, SOCK_STREAM, 0); Socket call có thể thất bại do nhiều nguyên nhân. Chẳng hạn, sự cố thiếu bộ nhớ (ENOBUFS), sự cố không hiểu protocol (EPROTONOSUPPORT), hoặc sự cố không có kiểu socket yêu cầu (EPROTOTYPE). 3- Đặt tên cho socket 13 Một socket khi tạo ra không có tên. Các process không thể truy cập socket, và do đó không có message nào được nhận trên nó, mỗi khi nó chưa được đặt tên. Các quá trình giao tiếp được ràng buộc bởi một liên kết. Trong Internet domain, liên kết này là local, foreign addresses và local, foreign ports. Trong UNIX domain liên kết này là local, foreign pathnames. Để đặt tên cho socket, ta dùng lời gọi hệ thống: bind (s, name, namelen); Ví dụ, Muốn đặt tên cho socket trong Internet address, ta có thể gọi: #include <sys/types.h> #include <netinet/in.h> … struct sockaddr_in sin; … bin (s, (struct sockaddr_in *) &sin, sizeof sin ); 4-Thiết lập cầu nối (Connection Establishment) Sự thiết lập cầu nối thường là không đối xứng, với một process là client và process kia là server. Server, khi muốn cung cấp các dòch vụ nào đó, phải đặt tên cho socket với một đòa chỉ đã biết tương ứng với dòch vụ và sau đó lắng nghe nột cách thụ động trên socket này. Còn client yêu cầu các dòch vụ mà server cung cấp bằng cách thiết lập một cầu nối tới socket của server bởi lời gọi hệ thống connect() . Ví dụ, trong Internet domain, lời gọi hệ thống có thể là: 14 Struct sockaddr_in server; … connect (s, (struct sockaddr *) &server, sizeof server); Có thể cầu nối không thể được thiết lập do nhiều nguyên nhân. Chẳng hạn: -ETIMEDOUT: Hết thời gian qui đònh cho việc cố gắng thiết lập cầu nối tới server (timeout) khi host mà server chạy trên đó bò down hoặc sự truyền tải trên mạng bò trục trặc do các nguyên nhân khác về phần cứng (card mạng bò hỏng…). -ECONNREFUSE: Host từ chối dòch vụ được yêu cầu khi server process chưa chạy hoặc tên dòch vụ được yêu cầu không đúng. Để nhận được yêu cầu kết nối từ client, server phải thực hai bước sau khi đã đặt tên cho sockket: -Lắng nghe các yêu cầu kếu nối từ client gởi tới (listen ()). -Khi có một yêu cầu kết nối gởi tới, có thể chấp nhận yêu cầu này (accept()). Ví dụ, trong Internet domain, hai bước trên có thể là: Struct sockaddr_in from; … listen(s, 5); fromlen = sizeof from; newsock = accept (s, (struct sockaddr *) &from, fromlen); 15 5-Truyền dữ liệu: Với một cầu nối đã được thiết lập, việc truyền dữ liệu có thể bắt đầu. Có nhiều cách gọi để thực hiện việc gởi (sending) và nhận (receiving) dữ liệu. Thực hiện việc truyền dữ liệu bằng lời gọi read () và write (). Read (s, buf, sizeof buf); Write (s, buf, sizeof buf); Thực hiện việc truyền dữ liệu bằng lời gọi send () và recv() Send (s, buf, sizeof buf, flags); Recv (s, buf, sizeof buf, flags); Giá trò của flags là rất quan trọng (flags được khai báo như những hằng số trong file <sys/socket.h>). Nó cho phép ta trực tiếp biến đổi nội dung dữ liệu trên socket sau lời gọi send () hoặc recv (). Ví dụ, Flags = MSG_PEEK cho phép ta chỉ dò trên socket xem đã có dữ liệu hay chưa, nội dung dữ liệu đó là gì, mà không thay đổi nội dung dữ liệu sau lời gọi. Do đó, lời gọi recv() hay read () có thể nhận lại dữ liệu trên socket sau khi dò. Điều này trang bò khả năng kiểm tra dữ liệu trước khi nhận. 6-Đóng socket: Sau khi thực hiện xong việc truyền dữ liệu và không cần dùng đến socket nữa, ta nên đóng socket lại bằng lời gọi hệ thống: Close (s); 16 Sau khi lời gọi được thực hiện, dữ liệu còn chưa xử lý trên socket sẽ chỉ được xử lý sau một thời gian nhất đònh, sau thời gian này nếu dữ liệu vẫn chưa xử lý xong vì một lý do nào đó thì nó sẽ bò mất. Nếu muốn tất cả dữ liệu trên socket sẽ được xử lý trước khi socket bò đóng, ta nên thực hiện lời gọi shutdown(). Shutdown (s, how); Giá trò how sẽ quyết đònh việc xử lý dữ liệu trước khi đóng socket s. 7-Socket kết khơng kết nối (connectionless sockets) Các bước trên được giới thiệu cho các sockets hướng kết nối (connection-oriented sockets). Còn đối với các datagram sockets dùng trong kỹ thuật truyền dữ liệu không kết nối đặc trưng cho các mạng chuyển mạch gói, giao diện được cung cấp là đối xứng. Nghóa là các processes có thể đóng hai vai trò client và server mà không cần thiết lập một cầu nối giữa chúng. Thực ra, đòa chỉ nguồn và đích đã được chứa trong message truyền đi trên socket. Các bước tạo và đặt tên cho socket là cần thiết cho việc truyền dữ liệu theo kiều datagram. Thậm chí không cần đặt tên cho socket cũng được, lúc đó hệ thống tự động lấy tên của host cục bộ cho socket. Các bước thiết lập cầu nối ở client và lắng nghe trên socket ở server là không cần thiết nữa (Trừ khi mong muốn các gói dữ liệu truyền đi theo những đòa chỉ nhất đònh và không thay đổi trong một khoảng thời gian dài). Việc gởi và nhận các gói (packets) dữ liệu có thể được thực hiện bởi các lời gọi sau: Sendto (s, buf, buflen, flags, (struct sockaddr *) &to, tolen); Recvfrom (s, buf, buflen, flags, (struct sockaddr *)&from, &fromlen); 8-Input/Output Multiplexing Ta có thể multiplex các yêu cầu I/O đối với các sockets (hoặc files) bởi lời gọi hệ 17 thống select(). Select() sẽ trả về 3 con trỏ tới 3 tập các socket có thể dọc, ghi dữ liệu và các exceptional conditions chờ xử lý. Ví dụ về cách sử dụng lời gọi select #include <sys/time.h> #include <sys/types.h> #include <sys/select.h> … fd_set readmask, writemask, exceptmask; struct timeval timeout; … select (nfds, & readmask, & writemask, & exceptmask, &ttimeou); Ta có thể thêm vào hoặc gở bỏ một socket vào 3 tập trên bởi các macro sau: FD_SET(fd, &mask), FD_CLR(fd, &mask), hoặc xóa rỗng một tập bởi FD_ZERO(&mask). Tham số timeout sẽ xác đònh xem chế độ của sự chọn lựa: 0 – kiểu poll, #0 – Trả về sau khoảng thời gian timeout, NULL – block. Tham số nfd = MAX(descriptors) + 1, chính là khoảng giá trò cho các sockets. Để kiểm tra xem một socket có thuộc tập các socket được chọn lựa không, ta có thể dùng macro FD_ISSET(fd, &mask). 18 Có rất nhiều lời gọi cho các thao tác được cung cấp bởi giao diện giao tiếp qua socket cần thiết trong quá trình phát triển các ứng dụng truyền dữ liệu giữa các processes trên mạng có thể tham khảo chi tiết trong bộ sách AT&T UNIX System V Release 4, Programmers’s Guide: Networking Interfaces của nhà xuất bản Pretice Hall. II- Semaphores Semaphore là một kỹ thuật đảm bảo cho tài nguyên dùng chung (shared resource) an toàn về mặt dữ liệu đối với sự truy cập đồng thời của các process. Lấy một ví dụ, trên hệ thống đường ray, một semaphore đảm bảo cho các đoàn tàu đang vận hành không đụng nhau ở các vùng giao nhau. Trong máy tính cũng tương tự như vậy. Nếu một process không kiểm tra semaphore trước khi truy cập tài nguyên dùng chung thì sự hỗn loạn (chaos) về dữ liệu sẽ xảy ra. Ta có thể lấy một ví dụ về sự nguy hiểm khi xảy ra sự hỗn loạn về dữ liệu khi truy cập tài nguyên dùng chung mà không dùng kỹ thuật semaphore. Giả sử ta có một đoạn chương trình rút tiền khỏi nhà băng theo tài khoản khai báo, với biến dùng chung cho các process là deposit là số tiền ký quỹ hiện hành của tài khoản khai báo. int deposit; void withdraw(int account, double money) { if (checkInAccount(account)) { deposit = getLastDeposit(account); if (deposit >= money) 19 deposit -=money; depositMoney(deposit); } } Giả sử có 2 người cùng rút tiền tại 2 ATM khác nhau cùng một lúc, nghóa là withdraw() được gọi cùng 1 lúc cho hai quá trình P1, P2. P1: còn 100, rút 50 , withdraw (1111, 50), còn 50 P2: còn 300, rút 70, withdraw (2222, 70), còn 230 Giả sử P1 gọi trước 1 chút, các bước kiểm tra điều hợp lệ và các bước xảy ra như sau: P1: …deposit = getLastDeposit (1111) = 100 100 > 50 Trao quyền cho P2 …deposit = getLastDeposit (2222) = 300 300 > 70 Trao quyền cho P1 deposit = 300 – 50 = 150 depositMoney(150) Kết thúc P1 và Trao Quyền cho P2 [...]... trong vùng nhớ của process đầu tiên khi hệ thống khởi động. ), và mỗi lúc một process nào đó muốn truy cập vào vùng nhớ này chỉ việc ánh xạ nó vào không gian đòa chỉ của process đây, ta giới hạn với các process trên cùng một host Muốn sử dụng dữ liệu của vùng nhớ chung chính xác, ta phải dùng kỹ thuật semaphore Việc ứng dụng shared memory và semaphore vào truyền dữ liệu giữa các process trên cùng một... on error */ key_t key; /* get semaphore-set-ID*/ int nsems; /* semaphore-set key */ int flags; /* option flags */ -Thao tác trên semaphore int semop (sid, ops, nops) /* return semaphore value prior to last operation or –1 on error*/ int sid; /* semaphore-set-ID*/ struct sembuf (*ops)[]; int nops; /* pointer to array of operations*/ /* number of operations */ -Hủy semaphore int semctl (sid, snum, command,... Kết thúc P2 Như vậy, sau cùng giá trò còn lại của tài khoản 1111 lại là 150, và tài khoản 22 22 là80 Chỉ là tưởng tượng nhưng thật là nguy kiểm Mọi việc sẽ được giải quyết nếu như ta được tìm cách ngăn cản chỉ có một process được phép truy cập tài nguyên chung mỗi lúc mà thôi Semaphore sẽ giải quyết việc này như sau: sem = createSemaphore(); /* Tạo semaphore*/ … enterCriticalSection(sem); /* Vào vùng... dữ liệu của tài nguyên dùng chung tồn tại trong các khoảng thời gian nhỏ này Như vậy , để xây dựng semaphore, ta không thể dùng các lệnh vó mô được mà phải dùng các lời gọi trang bò bởi kernel, ở đó chúng được bảo vệ khỏi sự tác động của các process System V có trang bò các lời goiï hệ thố ng thao tác trên semaphore như sau -Tạo semaphore int semget (key, nsems, flags) /* return semaphore-set-ID or... 0 ); } III-Shared Memory 23 Làm sao để một biến có thể dùng chung cho mọi process Nghóa là mỗi sự tác động lên giá trò của biến đó bởi một process đều thể hiện ở mọi process khác mà có tham khảo đến biến này Điều này không thể thực hiện được với việc khai báo biến thông thường cho dù có khai báo toàn cục Bởi vì mỗi process có vùng nhớ riêng của nó, các process không thể tham khảo vùng nhớ của nhau được... được khai báo toàn cục nhưng mỗi khi sinh ra process con, các tính chất của biến này được sao chép vào vùng nhớ dành riêng cho process con đó, mọi sự thay đổi giá trò trên biến này ở process cha và ở process con từ lúc đó không còn tác động lên nhau nữa (Trừ trường hợp thao tác với đòa chỉ I/O, nhưng lúc đó hậu quả là do bản chất của hệ thống) Như vậy, để có được một vùng nhớ chứa biến khai báo sao cho... int sid; 21 int snum; /* semaphore number */ int cmd; /* command */ char *arg; /* argument */ Các hàm yêu cầu ở trên có thể được xây dựng như sau: int createSemaphore() { int key =0; /* Tạo semaphore nhò phân, do đó tham số thứ 2 là 1*/ return semget((key_t) key, 1, 0666 | IPC_CREAT ); } void enterCriticalSection(int sem) { struct sembuf sb; sb.sem_num = 0; sb.sem_op = -1 ; sb.sem_flg = 0; 22 semop(sem,... message Các lời gọi gởi và nhận dữ liệu sẽ được xây dựng lại dựa trên việc đọc ghi trên một vùng nhớ chỉ ra trong shared memory và kỹ thuật semaphore đảm bảo sao cho receiver không đọc dữ liệu từ shared memory quá sớm hoặc sender không ghi dữ liệu vào shared memory cho tới khi nào receiver đã đọc hoàn tất System V có cung cấp một số lời gọi thao tác với shared memory như sau: -Xin cấp phát vùng nhớ... process khác truy cập vào*/ deposit = getLastDeposit(account); if (deposit >= money) deposit -= money; depositMoney(deposit); leaveCriticalSection(sem); /* Ra khỏi vùng chanh chấp, cho phép các process truy cập vào*/ releaseSemaphore(sem); /* Giải phóng semaphore */ 20 Khoảng thời gian chuyển tiếp giữa các lệnh vó mô điều có thể là điểm mà các process có thể trao quyền cho nhau, và do đó nguy cơ dẫn... thao tác với shared memory như sau: -Xin cấp phát vùng nhớ dùng chung kích thước nbytes bytes 24 int segid = shmget (key_t key, int nbytes, int flags); - nh xạ shared memory vào không gian đòa chỉ mà process quản lý để truy cập char *shmat (int segid, char *addr, int flags); -Bỏ ánh xạ int shmdt (char *addr); -Giải phóng shared memory int shmctl (int segid, int cmd, struct shmid_ds *sbuf); với cmd = . Trao quyền cho P2 …deposit = getLastDeposit (22 22) = 300 300 > 70 Trao quyền cho P1 deposit = 300 – 50 = 150 depositMoney(150) Kết thúc P1 và Trao Quyền cho P2 20 deposit =. 100, rút 50 , withdraw (1111, 50), còn 50 P2: còn 300, rút 70, withdraw (22 22, 70), còn 23 0 Giả sử P1 gọi trước 1 chút, các bước kiểm tra điều hợp lệ và các bước xảy ra như sau: P1: …deposit. deposit = 150 – 70 = 80 depositMoney(80) Kết thúc P2 Như vậy, sau cùng giá trò còn lại của tài khoản 1111 lại là 150, và tài khoản 22 22 là80. Chỉ là tưởng tượng nhưng thật là nguy kiểm.

Ngày đăng: 01/08/2014, 08:21

Tài liệu cùng người dùng

Tài liệu liên quan