Nội dung bài viết
Đăng ký học lập trình C++
Tại STDIO bạn được dạy nền tảng lập trình tốt nhất.
Đăng ký học
Khái niệm Server và Client mở rộng không chỉ nhằm hiểu về Server và Client trong lĩnh vực mạng máy tính. Đây là 2 khái niệm sẽ gây khó khăn cho chúng ta khi tiếp xúc với các nguồn tài liệu, công việc trong tương lai nếu như không có khái niệm về nó.

Giới thiệu

Bài viết này mong đợi giúp cho các bạn làm rõ hơn về 2 khái niệm Server và Client theo hướng lập trình và cố gắng mở rộng hơn 2 khái niệm này. Khi nắm bắt nhiều khái niệm hơn sẽ giúp cho ta nhanh chóng hiểu rõ các vấn đề, hoặc dùng các khái niệm để truyền tải thông tin một cách chính xác, có như vậy dự án hay công việc, học tập sẽ dễ dàng nhờ vào lượng thông tin đưa đi nhanh hơn.

Tuy nhiên, khái niệm này có thể được thấy trong nhiều lĩnh vực khác nhau, một cách linh động hơn ta có thể áp dụng trong nhiều công việc, ngữ cảnh khác.

Việc phân tách rõ hơn về Server và Client cũng giúp cho việc nhìn nhận phần chính và phần phụ trong công việc để ta biết và đầu tư hơn cho các công việc chính và giảm bớt sự đầu tư hơn cho các công việc phụ để tăng hiệu quả công việc.

Tiền đề bài viết

Trong quá trình đọc các tài liệu về lập trình, các tài liệu này được viết theo văn phong của phương Tây, có rất nhiều khái niệm mà chúng ta khó có thể hiểu được. Trong đó tôi có để ý 2 khái niệm này: Client Side và Server Side. Do khó có thể tìm ra được một định nghĩa chính xác cho 2 khái niệm này bởi vì đối với các tài liệu của phương Tây họ đã mặc định 2 khái niệm này là phải hiểu (vì đó là ngôn ngữ nói của họ), tôi xin sử dụng kinh nghiệm làm việc của mình để giải thích 2 khái niệm này.

Đối tượng của hướng đến

Bài viết dành cho lập trình viên là chủ yếu. Nhưng trong quá trình tìm hiểu về vấn đề này, tôi có thử nghiệm áp dụng cho nhiều lĩnh vực khác nhau và nó vẫn có thể giải quyết được các bài toán ở các lĩnh vực khác, nên đối tượng cho bài viết có thể mở rộng ra hơn.

Ngữ nghĩa của Server và Client

Từ tiếng Anh dịch sang tiếng Việt có thể hiểu Server là ai đó hoặc điều gì đó nhằm cung cấp hàng hóa, dịch vụ, ngược lại Client sẽ thừa hưởng các hàng hóa hoặc dịch vụ này.

Từ đó, ta hình thành nên một sơ đồ quan hệ giữa Server và Client là 1 phía (Server) sẽ cung cấp một dịch vụ, hàng hóa nào đó cho bên còn lại (Client). Ví dụ: hệ thống STDIO :: www.stdio.vn/ là Sever còn các bạn đọc là Client.

Server và Client đề cập trong bài này

Khi ta nhận được 1 yêu cầu, điều đó đồng nghĩa chúng ta chính là Server và người ra yêu cầu là Client.

Mức độ phân tách rõ ràng giữa Server và Client cũng tùy thuộc vào kinh nghiệm của từng người, ta xem xét 1 yêu cầu sau dành cho một người mới học lập trình: hãy viết một hàm trả về tổng của 2 số nguyên. Đôi lúc chúng ta sẽ nhận được kết quả như sau:

#include <stdio.h>

void sum(int a, int b)
{
    int c = a + b;
    printf("%d", c);
}

/*
int main()
{
    sum(5, 10);
}
*/

Phân tích codes trên ta thấy rằng, yêu cầu được đặt ra là viết hàm để tính tổng của 2 số, nhưng thật sự ta lại không nhận được kết quả chính xác này, vấn đề đặt ra là hàm sum(int a, int b) đã không thỏa mãn khái niệm Server (cung cấp dịch vụ), nó đã làm ra một kết quả khác, đó là kết quả của Client và thật ra việc có xuất kết quả ra màn hình hay không chính là quyết định của Client, ở đây Client đòi hỏi rằng muốn nhận được kết quả này thay vì xuất ra màn hình và thậm chí, hàm main() bên dưới sử dụng hàm sum cũng không được phép xuất hiện trong phần của Server (Nếu như chúng ta chỉ sử dụng hàm main để thực hiện Unit Test thì điều đó có thể chấp nhận được).

Đoạn codes trên nên được chỉnh sửa lại như sau để thỏa yêu cầu của Client hoặc chính nó làm việc đúng nghĩa của 1 Server.

int sum(int a, int b)
{
    int c = a + b;
    return c;
}

Server lúc này đã thực hiện đúng chức năng, và phần việc còn lại của Client muốn dùng nó vào việc gì là phần việc của Client. Mở rộng hơn nếu Client này được yêu cầu để làm một việc gì của một Client khác thì những đoạn code của Client đó lại là Server Code của các Client khác.

Các ví dụ khác

Để làm rõ hơn về 2 khái niệm này, chúng ta xét thêm 2 ví dụ sau.

Trong lập trình hướng đối tượng, xét ví dụ kế thừa kiểu public

/* SERVER SIDE */
class Community
{
private:
	int att1;

protected:
	int att2;

public:
	void Share()
	{
	
	}
};

/* XEM XÉT VIỆC KẾ THỪA KIỂU PUBLIC */
class Stdio: public Community
{
private:
	int att3;

public:
	void ShareArticle()
	{
	
	}
};

/* CLIENT SIDE
int main()
{
	Stdio obj;
}
*/

Xét việc khi đánh giá kế thừa kiểu public trên, chúng ta sẽ phải diễn đạt cho người khác hiểu việc kế thừa public sẽ ảnh hưởng như thế nào trong codes? Nếu phân tách rõ cho người nghe rằng, class Community và class Stdio lúc này được xem xét là Server Side, và việc kế thừa kiểu public chỉ có ý nghĩa với Client Side (class khác sử dụng Stdio, class con kế thừa Stdio, hay hàm main, bất kỳ hàm nào sử dụng Stdio).

Từ đó, ta tránh được các khái niệm mơ hồ như, "bên ngoài sẽ thấy", thay vì vậy ta giúp người nghe hiểu rõ hơn khi nói với họ, Server Side là đoạn nào và Client Side (bên ngoài) là đoạn nào, và người nghe sẽ hiểu được nhanh hơn.

Xét ví dụ về việc xét các số chẵn trong một mảng

Đoạn codes sau sẽ có vấn đề gì?

#include <stdio.h>

void GetEvenIntegersList(int* integersList, int n)
{
	for (int i = 0; i < n; n++)
	{
		if (integersList[i] % 2 == 0)
		{
			printf("%d", integersList[i]);
		}
	}
}

Với cách codes như trên, Server Codes này đã không thỏa mãn được chức năng Server của nó, lý do là các Client không thể sử dụng được dịch vụ này, các Client đã không nhận được danh sách số chẵn như mong đợi của nó. Điều này có thể không xảy ra với các lập trình viên đã có kinh nghiệm và kiến thức tốt nhưng ở các bạn chưa có kinh nghiệm thì điều này vẫn xảy ra trong lúc hiện thực hóa Server này, lý do nó đến từ kiến thức, nó đến từ kỹ năng và đôi lúc có chút "mất thời gian" khi phải làm thêm 1 số việc hoặc phải học thêm 1 số kiến thức, kỹ thuật nhỏ để hiện thực thành công Server. Xét đoạn codes đúng đắn hơn của Server bên dưới ta sẽ hiểu được điều này.

void GetEvenIntegersList(int* integersList, int n, int*& eIntegersList, int &m)
{
	// ĐẾM SỐ LƯỢNG SỐ CHẴN CÓ TRONG DANH SÁCH
	m = 0;

	for (int i = 0; i < n; i++)
	{
		if (integersList[i] % 2 == 0)
		{
			m++;
		}
	}

	if (m == 0)
		return;

	// KHỞI TẠO MẢNG ĐỦ ĐỂ CHỨA LƯỢNG SỐ CHẴN ĐÃ ĐẾM
	int* eIntegersList = new int[m];

	int k = 0;
	for (int i = 0; i < n; i++)
	{
		if (integersList[i] % 2 == 0)
		{
			eIntegersList[k++] = integersList[i];
		}
	}
}

Việc hiện thực đúng đắn một Server sẽ đòi hỏi nhiều kỹ năng hơn, lâu dài sẽ tạo nên một sự thói quen tốt và từ đó chúng ta học hỏi được nhiều hơn.

Đề cao Server và không phủ nhận Client

Server mang tính tập trung và cung cấp dịch vụ chính xác hơn cho Client, và Client này có thể là Server của 1 Client khác. Càng về sau, các Client sẽ càng gần với sản phẩm cuối cùng hơn và đó là mục tiêu của tất cả nhà phát triển, SẢN PHẨM CUỐI.

Sản phẩm cuối dùng để chinh phục người sử dụng (Client cuối cùng). Và Server lại giúp chúng ta ngày càng mạnh mẽ hơn, và hoàn thiện kỹ năng bản thân hơn và luôn luôn sẵn sàng phục vụ.

Mở rộng

Ngành nghề nào cũng sẽ đề cập mối tương quan giữa Server và Client, nếu biết vận dụng tốt, và tập trung vào các vấn đề chính (Server hoặc Client), phân tách rõ vai trò thì việc hiện thực hóa sẽ mang tính chính xác cao hơn.

Bài viết còn sơ khai, tôi sẽ còn cập nhật thêm. Hy vọng nhận được đóng góp của các bạn để bài viết hoàn thiện hơn.

THẢO LUẬN