TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN ĐIỆN TỬ VIỄN THÔNG BÀI TẬP LỚN MẠNG MÁY TÍNH Đề tài LẬP TRÌNH SOCKET ỨNG DỤNG CHIA SẺ FILE DÙNG CƠ CHẾ CLIENT SERVER Sinh viên thực hiện 20182498 BÙI TRẦN HIỂN 201. MỤC LỤC DANH MỤC HÌNH VẼ i DANH MỤC BẢNG BIỂU ii TÓM TẮT BÀI TẬP LỚN iii CHƯƠNG 1. GIỚI THIỆU CHUNG 1 1.1 Tổng quan về mạng máy tính . . . . . . . . . . . . . . . . . . . . . . . 1 1.1.1 Khái niệm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1.2 Lợi ích của mạng máy tính . . . . . . . . . . . . . . . . . . . . 2 1.2 Tổng quan về mạng máy tính . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.1 Bộ giao thức TCP (Transmission Control Protocol) . . . . . . . 2 1.2.1.1 Giới thiệu . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.1.2 Cấu trúc gói tin TCP . . . . . . . . . . . . . . . . . . 2 1.2.2 Bộ giao thức liên mạng (IP Protocol) . . . . . . . . . . . . . . 4 1.2.2.1 Đặc điểm của giao thức IP . . . . . . . . . . . . . . . 5 1.2.2.2 Cấu trúc gói tin . . . . . . . . . . . . . . . . . . . . 5 1.2.2.3 Cấu trúc địa chỉ IP . . . . . . . . . . . . . . . . . . . 7 CHƯƠNG 2. TỔNG QUAN VỀ SOCKET 9 2.1 Giới thiệu chung về Socket . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.1 Khái niệm Socket . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.2 Các loại Socket . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.3 Cấu trúc Socket . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2 Các hàm cơ bản dùng cho lập trình Socket . . . . . . . . . . . . . . . . 12 2.2.1 Hàm socket() . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.2 Hàm bind() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.3 Hàm connect() . . . . . . . . . . . . . . . . . . . . . . . . . . 132.2.4 Hàm listen() . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.5 Hàm accept() . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.6 Hàm send() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.7 Hàm recv() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.8 Hàm read() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.9 Hàm write() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.10 Hàm sendto() . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.11 Hàm recvfrom() . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2.12 Hàm fork() – Khởi tạo process . . . . . . . . . . . . . . . . . . 15 2.2.13 Hàm close() shutdown() . . . . . . . . . . . . . . . . . . . . . 15 2.2.14 Hàm thiết lập bộ nhớ memset() . . . . . . . . . . . . . . . . . 16 2.2.15 Hàm so sánh memcmp() . . . . . . . . . . . . . . . . . . . . . 16 2.2.16 Hàm copy bộ nhớ memcpy() . . . . . . . . . . . . . . . . . . . 16 2.2.17 getaddrinfo(), freeaddrinfo(), gaistrerror() . . . . . . . . . . . . 17 2.3 Mô hình TCP Socket dùng cơ chế Client – Server . . . . . . . . . . . . 17 2.3.1 Mô hình Client – Server . . . . . . . . . . . . . . . . . . . . . 17 2.3.2 Giao tiếp giữa Client and Server sử dụng TCP . . . . . . . . . . 18 CHƯƠNG 3. LẬP TRÌNH SOCKET ỨNG DỤNG CHIA SẺ FILE DÙNG CƠ CHẾ CLIENTSERVER 20 3.1 Giới thiệu về chương trình thiết kế . . . . . . . . . . . . . . . . . . . . 20 3.2 Phân tích chương trình và giao diện . . . . . . . . . . . . . . . . . . . 21 KẾT LUẬN 28 Kết luận chung 28 Hướng phát triển 28 TÀI LIỆU THAM KHẢO 29
Tổng quan về mạng máy tính
Khái niệm
Mạng máy tính là hệ thống gồm các thiết bị được kết nối hỗ trợ truyền dữ liệu qua các phương tiện truyền dẫn như dây dẫn, cáp, đảm bảo liên kết giữa các thiết bị như máy tính, máy in, máy scan và máy Fax Trong mạng máy tính, các thiết bị này hoạt động cùng nhau để chia sẻ thông tin và tài nguyên một cách hiệu quả Việc kết nối mạng giúp nâng cao năng suất làm việc, tối ưu hoá quá trình trao đổi dữ liệu và mở rộng khả năng truyền thông trong doanh nghiệp hoặc tổ chức Mạng máy tính đóng vai trò then chốt trong phát triển công nghệ thông tin và truyền thông hiện đại.
Mục đích của mạng máy tính là để gửi và nhận dữ liệu được lưu trữ trong các thiết bị khác qua mạng.
Có 5 thành phần cơ bản của mạng máy tính:
Hình 1.1 Các thành phần cơ bản của mạng máy tính
• Message: dữ liệu hay thông tin cần được truyền từ thiết bị này sang thiết bị khác qua mạng máy tính.
• Sender: thiết bị có dữ liệu và cần gửi dữ liệu đến thiết bị khác được kết nối với mạng.
• Receiver: thiết bị đang mong đợi dữ liệu từ thiết bị khác trên mạng.
• Transmission media: phương tiện truyền dẫn truyền dữ liệu từ thiết bị này qua thiết bị khác như dây dẫn, cáp, sóng radio,
Giao thức là tập hợp các quy tắc được cả người gửi và người nhận đồng ý, giúp đảm bảo quá trình giao tiếp giữa các thiết bị diễn ra thuận lợi Nếu không có giao thức, hai thiết bị có thể kết nối nhưng không thể trao đổi dữ liệu hiệu quả Để thiết lập một kết nối đáng tin cậy hoặc chia sẻ dữ liệu thành công giữa các thiết bị khác nhau, cần có một bộ quy tắc gọi là giao thức Giao thức đóng vai trò then chốt trong việc đảm bảo tính liên tục và bảo mật của quá trình truyền dữ liệu trong mạng internet.
HTTP và HTTPS là hai giao thức chính được trình duyệt web sử dụng để truy xuất và gửi dữ liệu trên Internet, đảm bảo hoạt động của các trang web an toàn và hiệu quả Ngoài ra, giao thức SMTP cũng đóng vai trò quan trọng trong việc gửi và nhận email qua Internet, giúp các dịch vụ email hoạt động liên tục và ổn định.
Lợi ích của mạng máy tính
Một số lợi ích của mạng máy tính:
• Mạng tạo khả năng dùng chung tài nguyên cho các người dùng
• Mạng cho phép nâng cao độ tin cậy
• Mạng giúp cho công việc đạt hiệu suất cao hơn
• Tăng cường tính bảo mật thông tin
• Việc phát triển mạng máy tính đã tạo ra nhiều ứng dụng mới
Tổng quan về mạng máy tính
Bộ giao thức TCP (Transmission Control Protocol)
TCP là giao thức truyền tải hướng kết nối, yêu cầu thiết lập kết nối trước khi gửi dữ liệu, giúp đảm bảo tính toàn vẹn và đáng tin cậy của thông tin truyền đi Quá trình thiết lập kết nối này được gọi là tiến trình bắt tay 3 bước (three-way handshake), nhằm thiết lập liên kết giữa hai thiết bị một cách chắc chắn trước khi dữ liệu được trao đổi.
Trong quá trình truyền dữ liệu giữa A và B, cơ chế báo nhận (Acknowledgement) đóng vai trò quan trọng để đảm bảo tính tin cậy của hệ thống Khi A gửi dữ liệu cho B, B sẽ gửi lại gói tin xác nhận (ACK) để thông báo đã nhận thành công dữ liệu đó Nếu A không nhận được tín hiệu xác nhận này, hệ thống sẽ tự động gửi lại dữ liệu hoặc thực hiện các biện pháp xử lý phù hợp nhằm đảm bảo dữ liệu được truyền chính xác và hoàn tất.
TCP sử dụng cơ chế đánh số thứ tự gói tin (sequencing) để đảm bảo dữ liệu được truyền chính xác đến điểm nhận Quá trình này giúp ghép các gói tin đúng thứ tự, loại bỏ các gói tin trùng lặp, từ đó duy trì tính toàn vẹn và đáng tin cậy của dữ liệu khi truyền qua mạng Đồng thời, TCP gửi các gói dữ liệu liên tục cho đến khi nhận được phản hồi xác nhận từ phía nhận, đảm bảo mọi gói đều được gửi thành công.
TCP có cơ chế điều khiển luồng (flow control) giúp tránh tình trạng tắc nghẽn mạng, đảm bảo dữ liệu truyền đi một cách ổn định Ngoài ra, TCP hỗ trợ chế độ truyền dữ liệu dạng đầy đủ (full-duplex), cho phép gửi và nhận dữ liệu cùng lúc trên một kết nối duy nhất Lớp này còn có chức năng phục hồi dữ liệu bị mất trong quá trình truyền, ví dụ nếu A gửi dữ liệu cho B mà không nhận được xác nhận, TCP sẽ tự động gửi lại để đảm bảo dữ liệu được truyền thành công.
1.2.1.2 Cấu trúc gói tin TCP
Do là giao thức tin cậy nên cấu trúc gói tin của TCP rất phức tạp
Hình 1.2 Cấu trúc bảng tin TCP
The source port and destination port, each 16 bits in length, are used to identify the specific application-layer protocol session associated with the TCP segment being transmitted.
• Sequence number (32 bit): dùng để đánh số thứ tự gói tin (từ số sequence nó sẽ tính ra được số byte đã được truyền).
• Acknowledge number (32 bit): dùng để báo đã nhận được gói tin nào và mong nhận được byte mang số thứ tự nào tiếp theo.
• Các bit reserverd (4 bit): đều được thiết lập bằng 0.
• Các bit control (9 bit): các bit dùng để điều khiển cờ (flag) ACK, cờ Sequence
• Window size (16 bit): số lượng byte được thiết bị sẵn sàng tiếp nhận.
• Checksum (16 bit): kiểm tra lỗi của toàn bộ TCP segment.
• Urgent pointer (16 bit): sử dụng trong trường hợp cần ưu tiên dữ liệu.
• Options (tối đa 32 bit): cho phép thêm vào TCP các tính năng khác.
• Data: dữ liệu của lớp trên.
Về vách thức hoạt động: TCP hoạt động theo tiến trình bắt tay 3 bước.
Hình 1.3 Cơ chế bắt tay 3 bước của TCP
Để host A truyền dữ liệu cho host B qua kết nối TCP, trước tiên cần thiết lập kết nối giữa hai máy chủ Quá trình này bắt đầu bằng việc host A gửi yêu cầu kết nối tới host B, thiết lập một kênh liên lạc đáng tin cậy và đảm bảo dữ liệu được truyền tải an toàn Việc thiết lập kết nối TCP bao gồm quá trình bắt tay ba bước (three-way handshake), nhằm đồng bộ các cổng và số hiệu thứ tự giữa hai host Sau khi kết nối được thiết lập thành công, host A có thể tiến hành gửi dữ liệu một cách an toàn và ổn định đến host B thông qua kết nối TCP.
Bước 1 trong quá trình thiết lập kết nối TCP là Host A gửi cho Host B một gói tin SYN với số hiệu thứ tự (Sequence Number) là 100, đánh dấu bắt đầu quá trình bắt tay TCP Gói tin này không chứa dữ liệu người dùng, nhưng vẫn được tính là 1 byte do hoạt động gửi cờ SYN Việc này giúp thiết lập liên kết ban đầu giữa hai host một cách chính xác và ổn định.
• Bước 2: Host B nhận được gói tin thì B gửi lại gói tin có cờ SYN được bật lên, kèm theo đó là cờ ACK để xác nhận.
Trong hệ thống mạng, khi host B thiết lập một segment với số thứ tự là 300, segment này không chứa dữ liệu nhưng vẫn được tính là 1-byte cho phần dữ liệu Khi phản hồi lại host A, host B cần rõ ràng trong phần ACK để chỉ ra số thứ tự của byte tiếp theo mà nó muốn nhận, dựa trên số thứ tự của segment SYN ban đầu Vì segment SYN do host A gửi được tính là 1-byte, host B sẽ mong muốn nhận byte tiếp theo là byte thứ 101 từ host A, nên ACK sequence của nó sẽ là 101, thể hiện rằng nó đã nhận được dữ liệu đến byte thứ 100 và đang chờ byte tiếp theo.
Sau khi kết nối được thiết lập, A gửi lại gói tin với số thứ tự SEQ = 101 để đáp ứng nhu cầu của B Gói tin này giúp thiết lập liên lạc chính xác và đảm bảo dữ liệu truyền tải đúng thứ tự Đồng thời, A gửi gói ACK có số thứ tự 301 để xác nhận đã nhận thành công gói tin có SEQ = 300 từ B, đảm bảo quá trình truyền dữ liệu diễn ra chính xác và đáng tin cậy.
Sau khi 3 bước được hoàn tất, kết nối TCP được thiết lập giữa host A và B, lúc này 2 host đã có thể truyền dữ liệu được với nhau.
Bộ giao thức liên mạng (IP Protocol)
Giao thức IP (Internet Protocol) là giao thức mạng hoạt động ở tầng 3 của mô hình OSI, quy định cách định địa chỉ máy tính và truyền tải các gói tin qua mạng IP được mô tả trong RFC 791, là thành phần chính của bộ giao thức liên mạng Cùng với TCP, IP trở thành phần lõi của giao thức Internet, đảm bảo truyền dữ liệu hiệu quả và toàn diện.
1.2.2.1 Đặc điểm của giao thức IP
•Là 1 trong những giao thức quan trọng nhất của bộ giao thức TPC/IP.
Giao thức IP là giao thức hướng không liên kết (connectionless), nghĩa là dữ liệu được truyền đi ngay lập tức nếu có thể theo phương thức "best effort" mà không cần thiết lập kết nối trước hay sử dụng cơ chế báo nhận và điều khiển luồng Các gói tin IP không được đánh số thứ tự khi trao đổi trên mạng, đảm bảo quá trình truyền dữ liệu diễn ra linh hoạt và nhanh chóng nhưng không đảm bảo độ tin cậy tuyệt đối.
•Mỗi gói tin IP được xử lý một cách hoàn toàn độc lập với các gói tin IP khác.
Giao thức IP sử dụng cơ chế định địa chỉ theo kiểu phân cấp, trong đó phần NetworkId giống như tên của một con đường giúp xác định mạng lưới một cách dễ dàng Phần hostId của địa chỉ đại diện cho số nhà trên con đường đó, cho phép xác định chính xác máy tính hoặc thiết bị trong mạng Hình thức phân cấp này giúp tối ưu hóa quá trình định tuyến và quản lý địa chỉ IP hiệu quả hơn trong hệ thống mạng toàn cầu.
Không có cơ chế khôi phục lại gói tin bị mất trên đường truyền, điều này được giao cho các giao thức tầng trên, như TCP, đảm nhiệm để đảm bảo độ tin cậy của dữ liệu truyền tải.
Gồm 2 phần là Header và data Header chứa thông tin quản lý của gói tin, data là phần dữ liệu cần truyền tải được đóng gói trong gói tin IP.
Hình 1.4 Cấu trúc gói tin IP Ý nghĩa các trường được mô tả như sau:
VERS (4 bit) xác định phiên bản IP hiện tại đang được sử dụng Nếu trường này không khớp với phiên bản IP của thiết bị nhận, thì các gói tin sẽ bị từ chối và loại bỏ Điều này đảm bảo rằng chỉ các gói tin phù hợp với phiên bản IP đáp ứng tiêu chuẩn hệ thống mới được chấp nhận, góp phần nâng cao hiệu quả và bảo mật mạng.
HLEN (IP Header Length - 4 bit) xác định độ dài của phần tiêu đề của datagram, được tính bằng đơn vị word (32 bits) Nếu trường này không có, độ dài mặc định của header thường là 20 byte (hoặc 5 words), giúp xác định phần tiêu đề IP một cách chính xác và tối ưu trong quá trình xử lý dữ liệu mạng.
• Service Type (8 bit): đánh dấu dữ liệu (marking) phục vụ cho tác vụ QoS với các gói tin IP
•Precedence (3 bit): chỉ thị quyền ưu tiên gửi datagram, cụ thể:
Hình 1.5 Chỉ thị quyền ưu tiên gửi datagram
•Delay (1 bit): chỉ độ trễ yêu cầu 0: độ trễ bình thường; 1: độ trễ thấp
•Throughput (1 bit):chỉ số thông lượng yêu cầu 0: thông lượng bình thường; 1: thông lượng cao
• Reliability (1 bit): chỉ độ tin cậy yêu cầu 0: độ tin cậy bình thường; 1: độ tin cậy cao
Chiều dài của gói tin IP được biểu diễn bằng trường Total Length (16 bit), tính theo đơn vị byte, bao gồm cả phần header Để xác định độ dài của dữ liệu, cần trừ đi giá trị của HLEN từ tổng chiều dài này Điều này giúp đảm bảo phân biệt rõ ràng giữa phần header và phần dữ liệu trong quá trình xử lýgói tin IP.
Trường định danh (16 bit) và các tham số như địa chỉ nguồn (Source address) cùng địa chỉ đích (Destination address) giúp xác định duy nhất mỗi Datagram gửi đi từ một trạm Phần định danh thường được tăng thêm 1 mỗi khi một Datagram mới được gửi đi, đảm bảo tính duy nhất và dễ theo dõi trong quá trình truyền dữ liệu.
•Flags (3 bit): Cờ sử dụng trong khi phân đoạn các Datagram.
Bit 0: reserved chưa sử dụng, giá trị luôn là 0.
Bit 1: DF = 1: Gói tin bị phân đoạn, có nhiều hơn 1 đoạn, DF = 0: Gói tin ko bị phân đoạn.
Bit 2: MF = 0: đoạn cuối cùng, MF = 1: chưa là đoạn cuối cùng, còn đoạn khác phía sau nữa.
• Fragment Offset (13 bit): Chỉ vị trí của đoạn phân mảnh (Fragment) trong IP Datagram tính theo đơn vị 64 Bit.
Thời gian sống (TTL) (8 bit) được sử dụng để chống vòng lặp gói tin IP khi gặp lỗi định tuyến trong mạng Giá trị TTL được thiết lập ban đầu khi gửi gói tin và giảm dần mỗi khi gói đi qua một router; nếu TTL về 0, gói tin sẽ bị loại bỏ để đảm bảo mạng hoạt động ổn định và tránh tình trạng vòng lặp vô hạn.
•Protocol (8 bit): nhận dạng giao thức nào đang được truyền tải trong phần data của gói tin IP, như TCP hay UDP.
Header checksum (8 bit) là phần kiểm tra lỗi của phần tiêu đề IP, giúp đảm bảo dữ liệu truyền đi chính xác Trong trường hợp kiểm tra này không thành công, gói dữ liệu sẽ bị huỷ bỏ để tránh gây ra lỗi trong quá trình truyền thông Việc sử dụng checksum giúp nâng cao tính toàn vẹn của dữ liệu và đảm bảo mạng hoạt động ổn định.
•Source Address (32 bit): địa chỉ của trạm nguồn.
•Destination Address (32 bit): địa chỉ của trạm đích.
•Option (có độ dài thay đổi):cho phép thêm vào tính năng mới cho giao thức IP.
Trong cấu trúc của gói IP, các tùy chọn (option) phải có độ dài là bội số của 32-bit theo quy định Nếu tùy chọn không đủ số bit cần thiết, các bit padding sẽ được thêm vào để đảm bảo đáp ứng yêu cầu này, giúp duy trì tính toàn vẹn và chuẩn xác của gói IP trong quá trình truyền tải dữ liệu.
•Data (độ dài thay đổi): vùng dữ liệu có độ dài là bội của 8 bit, tối đa là 65535 byte.
1.2.2.3 Cấu trúc địa chỉ IP
Địa chỉ IP là một dãy 32 bit nhị phân được chia thành 4 phần, mỗi phần gọi là một octet gồm 8 bit Các octet này được biểu diễn dưới dạng số thập phân và phân cách nhau bằng dấu chấm, giúp dễ dàng nhận diện và truyền đạt thông tin mạng Việc hiểu rõ cấu trúc của địa chỉ IP là cơ sở để quản lý và thiết lập các kết nối mạng hiệu quả.
•Địa chỉ IP được chia thành 2 phần: phần NetworkID (phần địa chỉ mạng) và phần HostID (phần địa chỉ máy trạm)
Trong một byte (8 bit), mỗi bit mang giá trị riêng biệt, với bit thấp nhất có giá trị 1 và bit cao nhất tương ứng với 128 Nếu tất cả 8 bit đều được đặt là 1, giá trị tối đa của một byte là 255 Điều này có nghĩa là byte có thể lưu trữ các số từ 0 đến 255, giúp đáp ứng hiệu quả các yêu cầu lưu trữ dữ liệu trong hệ thống máy tính.
Hình 1.6 Cấu trúc địa chỉ của IP
TỔNG QUAN VỀ SOCKET 9
Giới thiệu chung về Socket
Socket là giao diện lập trình ứng dụng mạng dùng để truyền và nhận dữ liệu qua internet, đảm bảo liên kết giao tiếp hai chiều (two-way communication) giữa hai chương trình chạy trên mạng Điểm cuối của liên kết này, gọi là socket, đóng vai trò quan trọng trong việc kết nối và trao đổi dữ liệu giữa các process trong môi trường mạng.
Chương trình mạng có thể sử dụng nhiều Socket cùng một lúc, nhờ đó nhiều ứng dụng có thể sử dụng Internet cùng một lúc.
Socket Interface trong UNIX BSD được định nghĩa dựa trên việc mở rộng các system calls để truy cập vào hệ thống tập tin, giúp hỗ trợ giao tiếp mạng hiệu quả Nhiều nền tảng khác nhau cung cấp API Socket với những điểm tương đồng nhỏ, tạo điều kiện thuận lợi cho lập trình viên phát triển ứng dụng mạng đa nền tảng Việc lập trình ứng dụng sử dụng Socket thường dựa trên hai giao thức chính của lớp vận chuyển là TCP và UDP, mang lại sự linh hoạt trong việc chọn phương thức truyền dữ liệu phù hợp với yêu cầu dự án.
Có 4 loại Socket có sẵn cho người dùng Hai loại đầu tiên được sử dụng phổ biến nhất và hai cái cuối cùng hiếm khi được sử dụng.
Các quá trình được cho là chỉ giao tiếp giữa các Socket cùng loại nhưng không có hạn chế nào cho việc giao tiếp giữa các Socket khác loại.
Stream Sockets sử dụng giao thức TCP (Transmission Control Protocol) để truyền dữ liệu giữa hai quá trình đã thiết lập kết nối, đảm bảo dữ liệu được truyền một cách chính xác và đáng tin cậy Vì quá trình truyền dữ liệu chỉ diễn ra sau khi kết nối đã được thiết lập giữa hai bên, hình thức này được gọi là Socket hướng kết nối, phù hợp cho các ứng dụng yêu cầu độ chính xác cao trong việc truyền dữ liệu.
Datagram sockets are used for connectionless protocols such as UDP (User Datagram Protocol), where establishing a connection is unnecessary Instead of setting up a persistent connection like stream sockets, datagram sockets allow for constructing individual data packets with destination information and sending them directly This approach makes datagram sockets ideal for lightweight, fast data transmission in scenarios where reliable connections are not required.
Raw Sockets là các giao thức cung cấp quyền truy cập vào các giao thức giao tiếp cơ bản, hỗ trợ trừu tượng hóa Socket Thông thường, loại Socket này hướng datagram, nhưng đặc điểm cụ thể phụ thuộc vào giao diện của từng giao thức Raw Sockets không dành cho người dùng phổ thông, mà chủ yếu dành cho các nhà phát triển muốn xây dựng các giao thức truyền thông mới hoặc truy cập vào các thành phần phức tạp của giao thức hiện có.
Sequenced Packet Sockets are similar to stream sockets but preserve record boundaries, making them essential in network system applications They enable users to manipulate headers of protocols like Sequenced Packet Protocol (SPP) or Internet Datagram Protocol (IDP) on individual or groups of data packets Users can embed prototype headers with outgoing data, define default headers for all transmissions, and receive headers on incoming packets, providing greater control over data communication This interface is a vital part of the network socket abstraction layer, facilitating precise packet management in various network applications.
Hình 2.1 Ví dụ về loại Socket
Trong lập trình Socket, các cấu trúc dữ liệu khác nhau được sử dụng để lưu trữ thông tin về địa chỉ, cổng và các dữ liệu liên quan khác, giúp quản lý kết nối hiệu quả Hầu hết các hàm liên quan đến Socket yêu cầu truyền vào một con trỏ đến cấu trúc địa chỉ Socket làm đối số, để xử lý các thông tin mạng chính xác Trong ví dụ này, chúng ta đã định nghĩa dạng dữ liệu cấu trúc trong ngôn ngữ C nhằm mô tả rõ ràng các thành phần của địa chỉ mạng và dễ dàng thao tác trong quá trình lập trình Socket.
The `sockaddr_in` structure is essential for defining socket addresses in network programming, containing key fields such as `sin_family`, which specifies the address family (typically AF_INET for IPv4), `sin_port`, a 16-bit port number expressed in Network Byte Order, and `sin_addr`, representing a 32-bit IP address also in Network Byte Order This structure facilitates the connection setup between host and network by providing necessary addressing information in a standardized format Understanding the components of `sockaddr_in` is crucial for configuring sockets in TCP/IP solutions.
Order.*/ unsigned char sin_zero[8];/* NULL, not being used */
•inaddr: sử dụng như một trường cấu trúc và chứa 32-bit netid/hostid struct in_addr { unsigned long s_addr; /* service port, A 32-bit IP address in Network Byte Order */
The 'hostent' structure is essential for storing information related to a network host, including the official host name, aliases, address type, address length, and a list of IP addresses Specifically, it contains fields such as 'h_name' for the primary host name, 'h_aliases' for alternative names, and 'h_addr_list' which holds one or more IP addresses associated with the host Typically used in Internet-based applications, the 'h_addrtype' is set to AF_INET, indicating IPv4 addresses This structure is fundamental for network programming and resolving host information efficiently.
The `servent` structure is used to store essential information about network services, including the official service name, aliases, associated port number, and the protocol used Specifically, it contains fields such as `s_name` for the service's official name, `s_aliases` for any alternate names, `s_port` for the port number tied to the service, and `s_proto` indicating the protocol, such as TCP or UDP This structure is crucial for managing service-related data in network programming.
Cấu trúc địa chỉ Socket là phần quan trọng không thể thiếu trong các chương trình mạng, giúp xác định chính xác điểm kết nối giữa các thiết bị Quá trình phân bổ, điền thông tin và chuyển các con trỏ tới địa chỉ socket phù hợp đóng vai trò quan trọng trong việc thiết lập và duy trì kết nối mạng hiệu quả.
Khi một hàm socket điền vào một cấu trúc, độ dài của cấu trúc cũng được truyền bằng tham chiếu để hàm có thể cập nhật giá trị của nó Chúng ta gọi đó là các đối số dạng giá trị-kết quả, giúp hàm trả về dữ liệu sau khi thực thi Để đảm bảo không có dữ liệu rác trong cấu trúc, luôn luôn khởi tạo các biến cấu trúc về NULL hoặc 0 bằng cách sử dụng hàm memset() hoặc hàm bzero() Việc này giúp tránh những lỗi không mong muốn do dữ liệu không xác định trong quá trình xử lý mạng.
Các hàm cơ bản dùng cho lập trình Socket
Chúng ta có thể liệt kê một số hàm cơ bản dùng cho lập trình Socket :
Bảng 2.1Một số hàm cơ bản trong lập trình Socket socket() accept() bind() read() / write() connect() send() / recv() sendto() / recvfrom() listen() close() shutdown()
#include int socket (int domain, int type, int protocol);
Hàm socket() tạo một socket, kết quả trả về là một số nguyên nhận dạng (socket descrip- tor), nếu có lỗi giá trị trả về là -1
Các tham số: domain (họ socket), type (kiểu socket), protocol (giao thức, thường được đặt = 0)
#include int bind(int sockfd, struct sockaddr *my_addr,int addrlen);
•Đăng ký socket đã khởi tạo với địa chỉ socket local
•Trả về 0 nếu thành công, -1 nếu thất bại
2.2.3 Hàm connect() int connect (int sockfd, struct sockaddr *serv_addr, int addrlen);
•Dùng cho chương trình client thiết lập kết nối đến server
•Trả về 0 nếu thành công, -1 nếu thất bại
2.2.4 Hàm listen() int listen(int sockfd, int backlog);
•Hàm listen() để kết nối đến server, khai báo độ dài hàng chờ
•Hàm này dùng cho chương trình server connection-oriented để đặt socket ở trạng thái chờ, lắng nghe kết nối từ phía client
•Trả về 0 nếu thành công, -1 nếu thất bại
2.2.5 Hàm accept() int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
•Chấp nhận kết nối từ client, tạo socket mới
•Giá trị là một socket descriptor của socket mới
•Trả về bộ mô tả không âm nếu thành công, nếu không sẽ trả về -1
2.2.6 Hàm send() int send(int sockfd, const void *msg, int len, int flags);
•Gửi dữ liệu tới một socket
• Trả về số bytes được gửi thành công, trả về -1 nếu thất bại, Số bytes được gửi thành công có thể nhỏ hơn số bytes thực sự muốn gửi
2.2.7 Hàm recv() int recv(int sockfd, void *buf, int len, int flags);
•Nhận dữ liệu từ một socket
•Trả về số bytes nhận được, trả về -1 nếu thất bại, Số bytes nhận được có thể nhỏ hơn số bytes yêu cầu bởi tham số len
2.2.8 Hàm read() int read(int sockfd, const void *buf, int len);
•Đọc dữ liệu từ connection vào bộ nhớ
•Trả về số bytes đọc được nếu thành công, trả về 0 nếu không có dữ liệu, trả về -1 nếu thất bại
2.2.9 Hàm write() int write(int sockfd, const void *buf, int len);
•Ghi dữ liệu từ bộ nhớ lên connection.
•Trả về số bytes ghi được nếu thành công, trả về -1 nếu thất bại
2.2.10 Hàm sendto() int sendto(int sockfd, const void *buf, int len, int flags, const struct sockaddr_in *toaddr, int toaddrlen);
•Gửi dữ liệu đến một địa chỉ socket từ xa
•Trả về số bytes gửi được nếu thành công, trả về -1 nếu thất bại
2.2.11 Hàm recvfrom() int recvfrom(int sockfd, const void *buf, int len, int flags, const struct sockaddr_in *fromaddr, int fromaddrlen);
•Nhận dữ liệu từ một địa chỉ socket từ xa
•Trả về số bytes gửi được nếu thành công, trả về -1 nếu thất bại
2.2.12 Hàm fork() – Khởi tạo process
#include pid_t fork(void);
•Khởi tạo các process, sử dụng trong multi-threading
• Nếu khởi tạo thành công, trả về hai giá trị: (-1 nếu lỗi) Trả về process ID của child’s process cho parent’s process, trả về 0 cho child’s process
•Type pidt defined in sys/types.h Normally, the process ID is an integer
#include int close(int sockfd);
#include int shutdown(int sockfd, int how);
•Hàm close() đóng một socket cả phía client và server, đồng thời giải phóng socket
•Hàm shutdown() đóng một phía client hoặc server, không giải phóng socket, vẫn phải gọi hàm close() khi muốn thực sự ngắt kết nối
•Trả về 0 nếu thành công và -1 nếu thất bại
•Trên windows platfrom gọi hàm closesocket()
2.2.14 Hàm thiết lập bộ nhớ - memset() void*memset(void*buffer,int ch,size_t count);
•Khởi tạo vùng bộ nhớ chỉ ra bởi con trỏ buffer, điền đầy count bytes đầu tiên của vùng bộ nhớ này bởi ch
•Trả về con trỏ chỉ tới vùng bộ nhớ buffer
2.2.15 Hàm so sánh memcmp() int memcmp(const void *buffer1, const void *buffer2, size_t count);
•So sánh ’count’ kí tự đầu tiên của 2 chuỗi buffer1và buffer2
2.2.16 Hàm copy bộ nhớ memcpy() void *memcpy( void *to, const void *from,size_t count);
•Copy count kí tự từ from sang to
Hàm này trả về giá trị là to, nghĩa là nó sẽ sao chép chính xác số byte cần thiết và không bao gồm byte cuối cùng của chuỗi Do đó, để sao chép n byte, bạn cần copy n+1 byte để đảm bảo toàn bộ dữ liệu mong muốn được sao chép chính xác.
#include int getaddrinfo(const char* node, const char* service, const struct addrinfo *hints, struct info **res); void freeaddrinfo (struct addrinfo *ai); const char *gai_strerror (int ecode);
•getaddrinfo() lấy thông tin về host name, service, và khởi tạo sockaddr bằng kết quả trả về
•Trả về 0 nếu thành công, khác 0 nếu có lỗi, bắt lỗi bằng hàm gaistrerror()
•freeaddrinfo() giải phóng bộ nhớ
Mô hình TCP Socket dùng cơ chế Client – Server
Hầu hết các ứng dụng mạng hiện nay đều dựa trên kiến trúc Client – Server, trong đó hai tiến trình hoặc ứng dụng giao tiếp để trao đổi dữ liệu Trong mô hình này, một tiến trình đảm nhận vai trò client, gửi yêu cầu đến server, trong khi tiến trình còn lại hoạt động như một server, xử lý các yêu cầu và trả kết quả về cho client Kiến trúc này đảm bảo sự phân chia rõ ràng giữa các chức năng và giúp tối ưu hóa quá trình truyền tải thông tin qua mạng.
Quy trình khách hàng thường bắt đầu bằng việc đưa ra yêu cầu cung cấp thông tin, sau đó nhận phản hồi từ hệ thống Ví dụ, trình duyệt Internet hoạt động như một ứng dụng máy khách gửi yêu cầu đến máy chủ Web để truy xuất nội dung trang web HTML Quá trình này có thể kết thúc hoặc tiếp tục với các xử lý bổ sung tùy theo phản hồi nhận được từ máy chủ.
Máy chủ (Server Process) là quá trình nhận yêu cầu từ khách hàng (client), xử lý các yêu cầu đó và gửi dữ liệu phản hồi phù hợp Sau khi hoàn thành, server luôn trong trạng thái sẵn sàng phục vụ các yêu cầu mới từ khách hàng khác Quá trình này đảm bảo hệ thống hoạt động liên tục, hiệu quả, giúp đáp ứng nhanh chóng mọi yêu cầu từ người dùng.
Máy chủ Web liên tục chờ đợi các yêu cầu từ Trình duyệt Internet, và ngay khi nhận được yêu cầu, nó sẽ lựa chọn trang HTML phù hợp để gửi lại cho trình duyệt đó Có hai loại kiến trúc Client – Server chính, giúp tối ưu hóa quá trình giao tiếp và truyền tải dữ liệu giữa các thành phần trong hệ thống mạng.
Two-tier architecture involves direct interaction between the client and server, which can pose security vulnerabilities and performance issues This architecture is used by browsers like Internet Explorer and web servers; to enhance security, SSL (Secure Socket Layer) is commonly deployed to address potential security concerns.
Kiến trúc 3 tầng (3-tier architectures) bao gồm một phần mềm trung gian gọi là ‘middleware’ nằm giữa Client và Server để thực hiện kiểm tra bảo mật và cân bằng tải trong các trường hợp tải nặng Middleware nhận tất cả các yêu cầu từ máy khách, xác thực yêu cầu rồi chuyển đến máy chủ để xử lý, sau đó phản hồi được gửi ngược lại qua middleware đến máy khách Các phần mềm middleware nổi bật như WebLogic và WebSphere giúp tối ưu hoá hiệu suất và bảo mật hệ thống.
Các loại máy chủ Server:
Server lặp lại (Iterative Server) là loại máy chủ đơn giản nhất, hoạt động theo mô hình xử lý yêu cầu từng lần một Trong hệ thống này, một tiến trình máy chủ đáp ứng một yêu cầu của khách hàng và sau khi hoàn thành, nó tiếp nhận yêu cầu mới từ khách hàng khác Trong khi đó, các khách hàng khác vẫn phải chờ đợi đến khi máy chủ xử lý xong yêu cầu hiện tại, dẫn đến hiệu suất phù hợp cho các hệ thống nhỏ hoặc tải thấp.
Máy chủ đồng thời là loại máy chủ chạy nhiều quy trình cùng lúc để phục vụ nhiều yêu cầu cùng một lúc, giúp giảm thời gian chờ đợi của khách hàng Phương pháp đơn giản để xây dựng máy chủ đồng thời trên Unix là phân nhánh một quy trình con để xử lý từng khách hàng riêng biệt, đảm bảo hiệu quả và hiệu suất cao.
2.3.2 Giao tiếp giữa Client and Server sử dụng TCP
Trong quá trình thiết lập kết nối bằng hệ thống gọi, Client và Server có những yêu cầu khác nhau, mặc dù đều dựa trên cấu trúc cơ bản của Socket Cả hai phía đều thiết lập các Socket riêng biệt để đảm bảo quá trình giao tiếp diễn ra thuận lợi và an toàn.
Các bước thiết lập kết nối một Socket ở phía Client như sau: •Tạo một Socket với the socket() system call
•Kết nối Socket với địa chỉ Server sử dụng the connect() system call
•Gửi và nhận dữ liệu Có một số cách để thực hiện việc này, nhưng cách đơn giản nhất là sử dụng the read() and write() system calls
Các bước thiết lập kết nối một Socket ở phía Server như sau: •Tạo một Socket với the socket() system call
•Liên kết Socket với một địa chỉ sử dụng the bind() system call Đối với một server socket trên Internet, địa chỉ bao gồm số cổng trên host.
•Lắng nghe các kết nối với the listen() system call
The accept() system call is essential for establishing network connections, as it waits for an incoming client connection This call typically blocks execution until a client successfully connects to the server, ensuring reliable communication setup between the client and server.
•Gửi và nhận dữ liệu bằng cách sử dụng the read() and write() system calls
Tương tác giữa Client và Server sử dụng TCP:
Hình 2.3 Quá trình giao tiếp giữa Client và Server dùng TCP
LẬP TRÌNH SOCKET ỨNG DỤNG CHIA SẺ FILE DÙNG CƠ CHẾ CLIENT-SERVER 20
Giới thiệu về chương trình thiết kế
Chúng em sử dụng ngôn ngữ Python để lập trình Socket cho ứng dụng chia sẻ file giữa Server và Client Hệ thống cho phép trao đổi file qua lại khi Server và Client được kết nối Các thư viện chính bao gồm thư viện socket của Python và tkinter để xây dựng giao diện người dùng Chương trình đặc biệt chú trọng hai hàm chính: truyền và nhận file, phản ánh chức năng cốt lõi thông qua quá trình giao tiếp TCP socket giữa Client và Server Đầu tiên, nhóm chúng em tập trung xây dựng hàm truyền file phía Server để thực hiện chức năng phát file tới Client một cách hiệu quả.
Hình 3.1 Hàm truyền file đi ở bên phía server
Tiếp theo hàm nhận file bên phía client được xây dựng.
Hình 3.2 Hàm nhận file ở bên phía client
Phân tích chương trình và giao diện
Chúng tôi đã thiết kế giao diện đơn giản giúp hình dung rõ ràng quá trình truyền và nhận file giữa Server và Client Chương trình hoạt động dựa trên nguyên lý chia thành hai phần chính: Server và Client, nhằm tối ưu hóa quá trình truyền dữ liệu và nâng cao trải nghiệm người dùng.
Trước tiên giao diện đăng nhập vào server được xây dựng để minh họa hoạt động của phần mềm.
Hình 3.3 Giao diện đăng nhập vào Server
Sau đó giao diện đăng nhập vào client được xây dựng.
Hình 3.4 Giao diện đăng nhập vào Client
Khi đăng nhập, người dùng cần nhập đúng tên đăng nhập và mật khẩu để truy cập vào hệ thống Trong đó, tài khoản và mật khẩu sử dụng cho phần đăng nhập là "admin" cho cả tên đăng nhập và mật khẩu Đầu tiên, người dùng cần nhập thông tin tài khoản và mật khẩu trên giao diện đăng nhập của server để có thể truy cập một cách an toàn và chính xác.
Hình 3.5 Giao diện Server khi nhập Username và Password
Tiếp theo, nhập mật khẩu và tài khoản vào giao diện đăng nhập vào client
Hình 3.6 Giao diện Client khi nhập Username và Password
Chương trình sẽ đăng nhập vào giao diện chính cho server và client như sau: Đầu tiên là giao diện của bên phía server.
Hình 3.7 Giao diện Server khi được đăng nhập
Tiếp theo là giao diện bên phía client:
Hình 3.8 Giao diện Client khi đăng nhập
Sau khi đã đăng nhập được vào trang làm việc chính trên server thì chúng ta có thể sử dụng được những tác vụ sau:
• Thao tác 1: Kích chuột vào mục List giao diện sẽ hiện lên danh sách các file trong server
Hình 3.9 Giao diện của chương trình khi thực hiện thao tác 1
• Thao tác 2: Kích chuột vào mục Refresh giao diện sẽ hiện lên Client đang kết nối với Server hiện tại
Hình 3.10 Giao diện của chương trình khi thực hiện thao tác 2
Sau khi đã đăng nhập được vào trang làm việc chính trên client thì chúng ta có thể sử dụng được những tác vụ sau:
• Thao tác 1:Kích chuột vào mục List giao diện sẽ hiện ra danh sách các tệp của Server mà Client này liên kết
Hình 3.11 Giao diện của Client khi thực hiện thao tác 1
• Thao tác 2: Nhập tên tệp mà mình muốn lưu vào mục File Name sau đó ấn Save
Hình 3.12 Giao diện nhập tệp redLD.jpg vào Client và thực hiện thao tác lưu thành công
Sau khi đã hoàn tất truyền file trên giao diện của phần mềm, ta tiến hành kiểm tra file được nhận về trên máy tính cá nhân
Hình 3.13 Thư mục clientdata khi khi chưa thực hiện thao tác 2
Sau khi thực hiện thao tác truyền file bằng phần mềm lập trình socket, quá trình chuyển file từ thư mục của máy chủ sang thư mục của khách hàng hoàn tất thành công Quá trình này đảm bảo dữ liệu được gửi chính xác và đầy đủ, phản ánh kết quả cuối cùng của việc truyền file qua mạng Việc sử dụng socket giúp nâng cao hiệu quả, độ tin cậy trong quá trình chia sẻ tệp tin giữa các thiết bị.
Hình 3.14 Thư mục clientdata khi thực hiện thao tác 2 đã có thêm tệp redLD
Bài tập lớn đã hoàn thành phần mềm lập trình socket chia sẻ file dựa trên cơ chế client-server Các lý thuyết liên quan được trình bày rõ ràng, kèm theo mã nguồn và mô phỏng chương trình theo từng bước để người đọc dễ dàng theo dõi Tổng kết, dự án đáp ứng đầy đủ các yêu cầu đề ra, bao gồm tóm tắt lý thuyết và mô phỏng hoạt động của socket thông qua ứng dụng chia sẻ file.
Trong tương lai, nhóm dự định cài đặt phần mềm trên từng máy tính cá nhân để tạo điều kiện chia sẻ file dễ dàng hơn Ngoài ra, nhóm sẽ thiết kế giao diện thân thiện, khoa học và bắt mắt nhằm thu hút người dùng Khi hoàn thiện các bước phát triển này, nhóm sẽ xuất bản phần mềm để tiếp cận rộng rãi đến tất cả mọi người.