Perl - Lập trình Socket

Socket là gì?

Socket là một cơ chế Berkeley UNIX tạo kết nối song công ảo giữa các quy trình khác nhau. Điều này sau đó đã được chuyển sang mọi hệ điều hành đã biết cho phép giao tiếp giữa các hệ thống qua vị trí địa lý chạy trên phần mềm hệ điều hành khác nhau. Nếu không có socket, hầu hết giao tiếp mạng giữa các hệ thống sẽ không bao giờ xảy ra.

Xem xét kỹ hơn; một hệ thống máy tính điển hình trên mạng nhận và gửi thông tin theo mong muốn của các ứng dụng khác nhau chạy trên đó. Thông tin này được chuyển đến hệ thống, vì một địa chỉ IP duy nhất được chỉ định cho nó. Trên hệ thống, thông tin này được cung cấp cho các ứng dụng liên quan, các ứng dụng này sẽ lắng nghe trên các cổng khác nhau. Ví dụ: một trình duyệt internet lắng nghe trên cổng 80 để biết thông tin nhận được từ máy chủ web. Ngoài ra, chúng tôi có thể viết các ứng dụng tùy chỉnh của mình có thể lắng nghe và gửi / nhận thông tin về một số cổng cụ thể.

Bây giờ, hãy tóm tắt rằng một ổ cắm là một địa chỉ IP và một cổng, cho phép kết nối để gửi và nhận dữ liệu qua mạng.

Để giải thích khái niệm socket đã đề cập ở trên, chúng ta sẽ lấy một ví dụ về Lập trình Máy khách - Máy chủ sử dụng Perl. Để hoàn thành kiến ​​trúc máy chủ khách hàng, chúng tôi sẽ phải thực hiện các bước sau:

Để tạo máy chủ

  • Tạo một ổ cắm bằng cách sử dụng socket gọi.

  • Liên kết ổ cắm với một địa chỉ cổng bằng bind gọi.

  • Nghe ổ cắm tại địa chỉ cổng bằng listen gọi.

  • Chấp nhận kết nối máy khách bằng accept gọi.

Để tạo khách hàng

  • Tạo một ổ cắm với socket gọi.

  • Kết nối (ổ cắm) với máy chủ bằng connect gọi.

Sơ đồ sau cho thấy trình tự hoàn chỉnh của các lệnh gọi được Máy khách và Máy chủ sử dụng để giao tiếp với nhau -

Cuộc gọi ổ cắm phía máy chủ

Cuộc gọi socket ()

Các socket()cuộc gọi là cuộc gọi đầu tiên trong việc thiết lập kết nối mạng là tạo một ổ cắm. Cuộc gọi này có cú pháp sau:

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

Lệnh gọi trên tạo ra một SOCKET và ba đối số khác là các số nguyên phải có các giá trị sau cho kết nối TCP / IP.

  • DOMAINphải là PF_INET. Có thể là 2 trên máy tính của bạn.

  • TYPE phải là SOCK_STREAM cho kết nối TCP / IP.

  • PROTOCOL nên là (getprotobyname('tcp'))[2]. Đó là giao thức cụ thể như TCP được nói qua socket.

Vì vậy, lệnh gọi hàm socket do máy chủ phát hành sẽ giống như thế này -

use Socket     # This defines PF_INET and SOCK_STREAM

socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2]);

Lệnh gọi bind ()

Các ổ cắm được tạo bởi lệnh gọi socket () sẽ vô dụng cho đến khi chúng được liên kết với tên máy chủ và số cổng. Máy chủ sử dụng những thứ saubind() chức năng chỉ định cổng mà họ sẽ chấp nhận kết nối từ máy khách.

bind( SOCKET, ADDRESS );

Ở đây SOCKET là bộ mô tả được trả về bởi lệnh gọi socket () và ADDRESS là địa chỉ socket (đối với TCP / IP) chứa ba phần tử:

  • Họ địa chỉ (Đối với TCP / IP, đó là AF_INET, có thể là 2 trên hệ thống của bạn).

  • Số cổng (ví dụ 21).

  • Địa chỉ internet của máy tính (ví dụ: 10.12.12.168).

Vì bind () được sử dụng bởi một máy chủ, máy chủ này không cần biết địa chỉ của chính nó nên danh sách đối số trông như thế này:

use Socket        # This defines PF_INET and SOCK_STREAM

$port = 12345;    # The unique port used by the sever to listen requests
$server_ip_address = "10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't bind to port $port! \n";

Các or die mệnh đề rất quan trọng vì nếu máy chủ chết mà không có kết nối chưa hoàn thành, cổng sẽ không thể sử dụng lại ngay lập tức trừ khi bạn sử dụng tùy chọn SO_REUSEADDR bằng setsockopt()chức năng. Đâypack_sockaddr_in() đang được sử dụng để đóng gói Cổng và địa chỉ IP thành định dạng nhị phân.

Cuộc gọi nghe ()

Nếu đây là một chương trình máy chủ, thì nó bắt buộc phải gọi đến listen()trên cổng được chỉ định để lắng nghe, tức là, chờ các yêu cầu đến. Cuộc gọi này có cú pháp sau:

listen( SOCKET, QUEUESIZE );

Cuộc gọi ở trên sử dụng bộ mô tả SOCKET được trả về bởi cuộc gọi socket () và QUEUESIZE là số lượng yêu cầu kết nối còn tồn đọng tối đa được phép đồng thời.

Cuộc gọi chấp nhận ()

Nếu đây là một chương trình máy chủ thì nó bắt buộc phải gọi đến access()chức năng chấp nhận các kết nối đến. Cuộc gọi này có cú pháp sau:

accept( NEW_SOCKET, SOCKET );

Bộ mô tả SOCKET chấp nhận cuộc gọi nhận được trả về bởi hàm socket () và sau khi hoàn thành thành công, bộ mô tả socket mới NEW_SOCKET được trả về cho tất cả các giao tiếp trong tương lai giữa máy khách và máy chủ. Nếu cuộc gọi access () không thành công, thì nó sẽ trả về FLASE được định nghĩa trong mô-đun Socket mà chúng ta đã sử dụng ban đầu.

Nói chung, accept () được sử dụng trong một vòng lặp vô hạn. Ngay sau khi một kết nối đến, máy chủ sẽ tạo một quy trình con để xử lý nó hoặc tự phục vụ nó và sau đó quay lại để lắng nghe các kết nối khác.

while(1) {
   accept( NEW_SOCKET, SOCKT );
   .......
}

Bây giờ tất cả các cuộc gọi liên quan đến máy chủ đã kết thúc và chúng ta hãy xem một cuộc gọi sẽ được khách hàng yêu cầu.

Cuộc gọi ổ cắm phía máy khách

Cuộc gọi kết nối ()

Nếu bạn chuẩn bị chương trình khách hàng, thì trước tiên bạn sẽ sử dụng socket() gọi để tạo một ổ cắm và sau đó bạn sẽ phải sử dụng connect()cuộc gọi để kết nối với máy chủ. Bạn đã thấy cú pháp cuộc gọi socket () và nó sẽ vẫn tương tự như lệnh gọi socket () máy chủ, nhưng đây là cú pháp choconnect() gọi -

connect( SOCKET, ADDRESS );

Ở đây SCOKET là bộ mô tả socket được trả về bởi lệnh gọi socket () do máy khách cấp và ADDRESS là địa chỉ socket tương tự như lệnh gọi ràng buộc , ngoại trừ việc nó chứa địa chỉ IP của máy chủ từ xa.

$port = 21;    # For example, the ftp port
$server_ip_address = "10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't connect to port $port! \n";

Nếu bạn kết nối với máy chủ thành công, thì bạn có thể bắt đầu gửi các lệnh của mình đến máy chủ bằng bộ mô tả SOCKET, nếu không máy khách của bạn sẽ xuất hiện bằng cách đưa ra thông báo lỗi.

Ví dụ về Máy khách - Máy chủ

Sau đây là mã Perl để triển khai một chương trình máy khách-máy chủ đơn giản bằng cách sử dụng ổ cắm Perl. Ở đây máy chủ lắng nghe các yêu cầu đến và khi kết nối được thiết lập, nó chỉ cần trả lời Smile từ máy chủ . Máy khách đọc tin nhắn đó và in ra màn hình. Hãy xem nó đã được thực hiện như thế nào, giả sử chúng ta có máy chủ và máy khách trên cùng một máy.

Tập lệnh tạo máy chủ

#!/usr/bin/perl -w
# Filename : server.pl

use strict;
use Socket;

# use port 7890 as default
my $port = shift || 7890;
my $proto = getprotobyname('tcp');
my $server = "localhost";  # Host IP running the server

# create a socket, make it reusable
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "Can't open socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "Can't set socket option to SO_REUSEADDR $!\n";

# bind to a port, then listen
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't bind to port $port! \n";

listen(SOCKET, 5) or die "listen: $!";
print "SERVER started on port $port\n";

# accepting a connection
my $client_addr;
while ($client_addr = accept(NEW_SOCKET, SOCKET)) {
   # send them a message, close connection
   my $name = gethostbyaddr($client_addr, AF_INET );
   print NEW_SOCKET "Smile from the server";
   print "Connection recieved from $name\n";
   close NEW_SOCKET;
}

Để chạy máy chủ ở chế độ nền, hãy sử dụng lệnh sau trên dấu nhắc Unix:

$perl sever.pl&

Tập lệnh tạo khách hàng

!/usr/bin/perl -w
# Filename : client.pl

use strict;
use Socket;

# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 7890;
my $server = "localhost";  # Host IP running the server

# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
   or die "Can't create a socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't connect to port $port! \n";

my $line;
while ($line = <SOCKET>) {
   print "$line\n";
}
close SOCKET or die "close: $!";

Bây giờ chúng ta hãy bắt đầu ứng dụng khách của chúng ta tại dấu nhắc lệnh, sẽ kết nối với máy chủ và đọc thông báo do máy chủ gửi và hiển thị tương tự trên màn hình như sau:

$perl client.pl
Smile from the server

NOTE - Nếu bạn đang cung cấp địa chỉ IP thực ở dạng ký hiệu dấu chấm, thì bạn nên cung cấp địa chỉ IP ở cùng định dạng ở cả máy khách và máy chủ để tránh bất kỳ sự nhầm lẫn nào.