Perl 소켓 프로그래밍


소켓은 "소켓"이라고도 합니다. 애플리케이션은 일반적으로 "소켓"을 통해 네트워크에 요청을 보내거나 네트워크 요청에 응답하므로 컴퓨터의 호스트나 프로세스가 통신할 수 있습니다.

이 장에서는 Perl 언어로 소켓 서비스를 사용하는 방법을 설명합니다.


서버 생성

  • 소켓 서비스를 생성하려면 socket 함수를 사용하세요.

  • 포트를 바인딩하려면 bind 기능을 사용하세요.

  • 포트에서 들으려면 듣기 기능을 사용하세요.

  • 클라이언트 요청을 받으려면 accept 기능을 사용하세요.

클라이언트 생성

  • 소켓 서비스를 생성하려면 소켓 함수를 사용하세요.

  • 소켓 서버에 연결하려면 connect 함수를 사용하세요.

다음 다이어그램은 클라이언트와 서버 간의 통신 프로세스를 보여줍니다.


서버 소켓 기능

소켓 함수

Perl에서는 소켓을 생성하기 위해 소켓() 함수를 사용합니다. 구문 형식은 다음과 같습니다.

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

매개변수 분석:

  • DOMAIN ​​​​생성된 소켓에 설정된 프로토콜을 지정합니다. 예:


    • AF_INET은 IPv4 네트워크 프로토콜을 나타냅니다.

    • AF_INET6은 다음을 나타냅니다. IPv6

    • AF_UNIX은 로컬 소켓을 나타냅니다(파일 사용)

  • TYPE 소켓 유형 연결 지향형인지 비연결형인지에 따라 SOCK_STREAM 또는 SOCK_DGRAM으로 나눌 수 있습니다

  • PROTOCOL(getprotobyname('tcp')이어야 합니다. )[2] . 사용되는 실제 전송 프로토콜을 지정합니다.

따라서 소켓 함수는 다음과 같이 호출됩니다.

use Socket     # 定义了 PF_INET 和 SOCK_STREAM

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

bind() 함수는

bind()를 사용하여 소켓에 주소를 할당합니다. :

bind( SOCKET, ADDRESS );

SOCKET 소켓 설명자입니다. ADDRESS는 세 가지 요소를 포함하는 소켓 주소(TCP/IP)입니다:

  • 주소 클러스터(TCP/IP, AF_INET, 시스템에서는 2일 수 있음)

  • 포트 번호(예: 21)

  • 네트워크 주소(예: 10.12.12.168)

소켓()을 사용하여 생성 소켓이 생성된 후에는 소켓이 사용하는 프로토콜만 할당되고 주소는 할당되지 않습니다. 다른 호스트로부터의 연결을 수락하기 전에 바인딩()을 호출하여 소켓에 주소를 할당해야 합니다.

간단한 예시는 다음과 같습니다.

use Socket        # 定义了 PF_INET 和 SOCK_STREAM

$port = 12345;    # 监听的端口
$server_ip_address = "10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "无法绑定端口! \n";

or die 주소 바인딩 실패 후 실행됩니다.

setsockopt() 옵션 SO_REUSEADDR을 설정하여 즉시 재사용할 수 있는 포트를 설정하세요.

pack_sockaddr_in() 함수는 주소를 바이너리 형식으로 변환합니다.

listen() 함수

소켓이 주소에 바인딩되면 Listen() 함수는 가능한 연결 요청을 수신하기 시작합니다. 그러나 이는 안정적인 데이터 흐름이 보장되는 경우에만 사용할 수 있습니다.

listen( SOCKET, QUEUESIZE );

SOCKET: 소켓 설명자입니다.

QUEUESIZE: 연결 요청이 도착하면 수신 대기열에 들어가고 accept()에서 연결 요청이 제거됩니다. 대기열이 가득 차면 새 연결 요청이 오류를 반환합니다.

연결이 승인되면 성공 시 0을, 오류 시 -1을 반환합니다.

accept() 함수

accept() 함수는 요청된 소켓 연결을 수락합니다. 성공하면 네트워크 주소의 압축된 형식을 반환하고, 그렇지 않으면 FALSE:

accept( NEW_SOCKET, SOCKET );

SOCKET: 소켓 설명자를 반환합니다.

ADDRESS: ADDRESS는 세 가지 요소를 포함하는 소켓 주소(TCP/IP)입니다.

  • 주소 클러스터(TCP/IP, AF_INET, 귀하의 컴퓨터에 있을 수 있음) 시스템 예 2)

  • 포트 번호(예: 21)

  • 네트워크 주소(예: 10.12.12.168)

accept()는 일반적으로 무한 루프에서 사용됩니다.

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

위의 예는 클라이언트 요청을 실시간으로 모니터링할 수 있습니다.


클라이언트 함수

connect()

connect() 시스템 호출 함수는 소켓에 대한 연결을 설정합니다. 매개변수는 파일 설명자와 호스트 주소입니다.

connect( SOCKET, ADDRESS );

다음은 서버 소켓에 연결된 인스턴스를 생성합니다.

$port = 21;    #  ftp 端口
$server_ip_address = "10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
    or die "无法绑定端口! \n";

전체 인스턴스

다음으로 전체 예제를 사용하여 모든 소켓 기능을 이해합니다. 애플리케이션:

Server server.pl 코드:

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

use strict;
use Socket;

# 使用端口 7890 作为默认值
my $port = shift || 7890;
my $proto = getprotobyname('tcp');
my $server = "localhost";  # 设置本地地址

# 创建 socket, 端口可重复使用,创建多个连接
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "无法打开 socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "无法设置 SO_REUSEADDR $!\n";

# 绑定端口并监听
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "无法绑定端口 $port! \n";

listen(SOCKET, 5) or die "listen: $!";
print "访问启动:$port\n";

# 接收请求
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 "我是来自服务端的信息";
   print "Connection recieved from $name\n";
   close NEW_SOCKET;
}

터미널을 열고 다음 코드를 실행하세요:

$ perl sever.pl
访问启动:7890

Client client.pl 코드:

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

use strict;
use Socket;

# 初始化地址与端口
my $host = shift || 'localhost';
my $port = shift || 7890;
my $server = "localhost";  # 主机地址

# 创建 socket 并连接
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
   or die "无法创建 socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "无法连接:port $port! \n";

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

다른 터미널 열기 그리고 다음 코드를 실행하세요:

$ perl client.pl
我是来自服务端的信息