CN_1_4_Socket



1.4 Socket API

Socket API là bộ thư viện lập trình ứng dụng, được sử dụng nhiều nhất để viết các ứng dụng trên mạng hiện nay.

Giao tiếp giữa ứng dụng và mạng (network-application)

Quan sát hình vẽ sau:

Hình vẽ trên thể hiện một hệ thống gồm: hai host được kết nối với nhau qua hệ thống mạng của ISP, trên các host có cài đặt các ứng dụng mạng (app), các ứng dụng mạng sử dụng thành phần giao tiếp (interface) để trao đổi thông tin với hệ thống mạng.
Thành phần giao tiếp sẽ định nghĩa và cung cấp cách thức để app có thể trao đổi thông tin với hệ thống mạng, để cuối cùng, app trên máy tính này có thể “nói chuyện” được với app trên máy tính khác.
Nhờ vào thành phần giao tiếp, ứng dụng chỉ làm việc trực tiếp với host (hay local host), mà không cần quan tâm tới tổ chức thực sự ở bên dưới của hệ thống mạng (cơ chế này giúp che dấu sự phức tạp của hệ thống). Ngược lại, hệ thống mạng cũng không quan tâm tới ứng dụng gì đang chạy ở host mà chỉ quan tâm tới việc chuyển các gói tin đi tới đúng đích cần tới.

Ứng dụng client-server


Hình vẽ trên minh họa ứng dụng client-server.
Thông qua hệ thống mạng, chương trình client (ứng dụng trên host client) sẽ gửi yêu cầu (request) tới chương trình server (ứng dụng trên host server). Khi nhận được yêu cầu, chương trình server sẽ đáp ứng lại (reply). Đây là một nguyên lý vận hành cơ bản của rất nhiều các ứng dụng trên mạng. Ví dụ:
  • Dịch vụ FTP (send name, get file): client gửi tên tập tin cần lấy, server sẽ gửi về nội dung của tập tin.
  • Duyệt web (send URL, get page): client gửi địa chỉ trang web, server sẽ gửi về nội dung của trang web.
  • Ứng dụng ping (send message, get message): client gửi gói tin tới server, server sẽ gửi lại gói tin phản hồi.
Socket API cung cấp môi trường lập trình, giúp người lập trình thuận lợi hơn trong việc xây dựng các ứng dụng mạng. Tất cả các hệ điều hành và ngôn ngữ lập trình quan trọng hiện nay đều có hỗ trợ socket API. Khởi nguồn, socket API được nhúng vào hệ điều hành Berkeley (một phiên bản của UNIX) năm 1983.
Socket API cung cấp hai loại dịch vụ mạng: streams và datagrams
  • Streams: truyền có đảm bảo các luồng byte dữ liệu (reliably).
  • Datagrams: truyền không đảm bảo các gói dữ liệu rời rạc.
Quan sát ví dụ về socket API.


Ở hình trên, ứng dụng mạng app được cài đặt trên máy host, app sử dụng cấu trúc dữ liệu socket để gắn kết app với hệ thống mạng. Mỗi socket sử dụng một số để phân biệt, gọi là port number, đây cũng là một dạng địa chỉ. Socket bên trái có port number là 2 và bên phải là 2. Nhờ vào địa chỉ này, cho phép chạy nhiều ứng dụng cùng lúc trên một host.
Bảng sau cung cấp một số lời gọi API quan trọng của socket.
Tên
Ý nghĩa
SOCKET
Tạo một socket mới.
BIND
Gắn kết địa chỉ cục bộ của host với socket.
LISTEN
Chuẩn bị để chấp nhận yêu cầu kết nối
ACCEPT
Sẵn sàng chấp nhận kết nối.
CONNECT
Chủ động thiết lập một kết nối.
SEND
Gửi byte dữ liệu tới ứng dụng khác trên mạng thông qua kết nối.
RECEIVE
Nhận byte dữ liệu từ ứng dụng khác trên mạng thông qua kết nối.
CLOSE
Đóng kết nối.
Quá trình sử dụng socket được minh họa trong hình sau:

Hình trên minh họa quá trình trao đổi thông tin giữa hai máy tính trên mạng (client, và server) theo thời gian. Chiều mũi tên ngang thể hiện hướng truyền của dữ liệu, nét đứt thể hiện thông tin điều khiển, nét liền là truyền dữ liệu thực sự.
Đầu tiên, cần tạo một kết nối giữa client và server (connect), sau đó client có thể gửi yêu cầu tới server (request), khi nhận được yêu cầu từ client, server sẽ đáp ứng lại yêu cầu của client (reply), cuối cùng sau khi hoàn tất việc truyền dữ liệu, hai bên sẽ đóng kết nối (disconnect).
Số thứ tự (từ 1 đến 10) thể hiện thứ tự thực hiện các lời gọi hàm.
  • Lời gọi hàm đầu tiên được thực hiện ở cả client và server là socket, để thiết lập một socket(1) mới cho quá trình giao tiếp.
  • Bind(2): giúp đảm bảo khi client kết nối tới server, client sẽ kết nối tới một cổng cụ thể trên server cụ thể. Đây là quá trình thiết lập địa chỉ cho giao tiếp tại đầu cuối.
  • Sau đó là listen(3) và accept(4), giúp socket sẵn  sàng chấp nhận yêu cầu kết nối từ phía client (giống như ngồi sẵn bên điện thoại cố định để chờ cuộc gọi tới).
  • Phía client gửi yêu cầu kết nối tới server, connect(5). (bấm số để thực hiện một cuộc gọi điện thoại)
  • Phía server tiếp nhận yêu cầu kết nối, recv(6) (nhấc máy điện thoại lên nghe, sẵn sàng nhận thông tin)
  • Khi kết nối đã được thiết lập, quá trình gửi yêu cầu được thực hiện từ phía client, send(7) request.
  • Server đáp ứng lại yêu cầu của phía client, send(9) reply.
  • Quá trình nhận kết quả được thực hiện tại phía client, recv(8).
  • Sau khi hoàn tất quá trình giao tiếp, hai bên sẽ đóng kết nối, close(10).
Chú ý: bước 4 là accept, trong khi connect lại là bước 5, nghĩa là chấp nhận kết nối trước khi có yêu cầu kết nối? Thực tế, accept là một khối lệnh, accept thông báo cho hệ thống mạng ở vào trạng thái đợi và chấp nhận một kết nối (giống như thông báo cho một người tới ngồi gần điện thoại cố định để chờ có cuộc gọi tới).

Đoạn mã lập trình phía client

socket()                     //tạo socket
getaddrinfo()              //tên server, cổng kết nối
                                 //www.example.com:80
                                 //getaddrinfo cũng thực hiện việc chuyển đổi địa chỉ dạng
                                 www.example.com sang địa chỉ IP.
connect()                   //khối lệnh kết nối tới server
send()                        //gửi yêu cầu
recv()                        //khối lệnh đợi trả lời từ phía server
                             //thực hiện các thao tác trên dữ liệu nhận được từ server
close()                       //đóng kết nối

Đoạn mã lập trình phía server

socket()                     //tạo socket
getaddrinfo()              //thực hiện việc chuyển đổi qua lại giữa các loại địa chỉ
bind()                        //gắn kết port với socket
listen()                       //chuẩn bị để chấp nhận yêu cầu kết nối
------------------//vòng lặp
{accept()                   //đợi kết nối [khối lệnh]
...
recv()                        //đợi yêu cầu từ phía client
                            
send()                        //gửi lại dữ liệu theo yêu cầu từ phía client
---------------------//hết lặp
close()                       //đóng kết nối

Tham khảo:

[1] Andrew S. Tanenbaum, David J. Wetherall, Computer Networks 5th edition, 2011
[2] David J. Wetherall, Introduction to Computer Networks, www.coursera.org, 2013
----------------------
2013/7/17