PERL SOCKET編程

來源:互聯網
上載者:User

用PERL SOCKET

使用PERL SOCKET API首先需要載入SOCKET模組。
use Socket;
======================================================================
socket(檔案控制代碼,AF_INET,資料類型,協議類型);
#建立通訊端

檔案控制代碼隨便找個詞就可以了。
AF_INET為域類型,也可以寫為PF_INET。
資料類型,通常用有兩種:SOCK_STREAM、SOCK_DGRAM。
協議類型,可以用協議號代替,EGP---8、HMP---20、ICMP---1、
RAW---255、RDP---27、RVD---66、TCP---6、UDP---17、XNS-IDP---22、
其他---22、ALL---0;也可以用getprotobyname()函數作此參數。

例子:socket(SOCK,AF_INET,SOCK_STREAM,getprotobyname('tcp'));
語柄為SOCK,通訊端以TCP方式傳輸。
socket(SS,AF_INET,SOCK_DGRAM,17);
語柄為SS,通訊端以UDP方式傳輸。

=======================================================================
connect(檔案控制代碼,sockaddr_in結構體);
#串連主機

-----------------------------------------------
sockaddr_in結構體:

$address=inet_aton(地址);
$port=連接埠號碼;

$result=sockaddr_in($port,$address);

#上面的$result就是sockaddr_in結構體,執行個體:

$address=inet_aton(127.0.0.1);
$port=80;
$result=sockaddr_in($port,$address);
-----------------------------------------------

例子:connect(SOCK,$result);

=======================================================================
bind(通訊端,sockaddr_in結構體);
#綁定伺服器主機地址與連接埠(用於服務端)

例子:bind(SOCK,$result);

=======================================================================
listen(通訊端,等待串連最大隊列數);
#設定連接埠狀態為監聽(用於服務端)

例子:listen(SOCK,10);

=======================================================================
accept(遠程通訊端,服務端監聽通訊端)
#接收遠端資料請求,建立串連(用於服務端)

例子:accept(SESSION,SOCK);

=======================================================================
close(檔案控制代碼);

close 檔案控制代碼;
#關閉通訊端

例子:close(SOCK);
close SS;

●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●

說說TCP的網路活動順序:

=======================================================================
Client(用戶端):

建立通訊端socket()->串連到目標主機connect()->開啟autoflush模式autoflush()->
I/O操作->關閉通訊端close()

 

Server(伺服器):

建立通訊端socket()->綁定伺服器位址與連接埠bind()->設定監聽狀態listen()->接受遠程通訊端accept()->
開啟autoflush模式autoflush()->I/O操作->關閉通訊端close()

●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●

◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎
PERL SOCKET API編程執行個體:

附:I/O操作暫時只使用print()與<>符號。
=======================================================================
#!usr/bin/perl
#用戶端
use IO::Handle; #掛起IO::Handle
use Socket; #調用SOCKET
$port=80; #串連遠程主機的80連接埠
$host='localhost'; #使用迴路位址
$packhost=inet_aton($host); #壓縮IP地址
$address=sockaddr_in($port,$packhost); #壓成sockaddr_in格式
socket(CLIENT,AF_INET,SOCK_STREAM,6); #通訊端為CLIENT,使用TCP協議
connect(CLIENT,$address); #串連
CLIENT->autoflush(1); #開啟AUTOFLUSH模式
$msg_in= #INPUT
print "IN:$msg_in/n"; #OUTPUT
close CLIENT; #關閉通訊端
exit 1; #退出程式
=======================================================================
#!usr/bin/perl
#服務端
use IO::Handle; #掛起IO::Handle
use Socket; #調用SOCKET
$port=80; #綁定的伺服器主機連接埠為80
$address=sockaddr_in($port,INADDR_ANY); #壓成sockaddr_in格式,使用INADDR_ANY萬用字元
socket(SERVER,AF_INET,SOCK_STREAM,getprotobyname('tcp')); #通訊端為SERVER,使用TCP協議
bind(SERVER,$address); #綁定
listen(SERVER,10); #設定監聽狀態
while(1){ #進入I/O交換迴圈體
next unless (accept(CLIENT,SERVER));
CLIENT->autoflush(1);
print CLIENT "WHAT DO YOU WANT?/n";
close CLIENT;}
close SERVER; #關閉通訊端
exit 1; #退出程式
=======================================================================
執行個體註解:

1)TCP的client與server代碼中有一行'SOCK->autoflush(1);',正常情況下下面的I/O代碼是會先進入緩衝,
再輸出的,但加了上面的代碼就可以跳過這一步直接輸出了。此代碼需要積極式載入IO::Handle。

2)INADDR_ANY萬用字元的值在Socket模組中已經定義了,其值為本網適配的所有網路介面(包括迴路位址、
廣播位址、多播地址等)。
◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎
頭有點痛,寫到這裡,下回介紹send()與recv()........:P

[日記文]'send()' and 'recv'[perl_sock 2]

writer:demonalex
email:demonalex_at_dark2s.org

附接上文的某些內容,最後使用的兩個C/S程式中的資料交換部分使用了PERL I/O,
現在介紹一下PERL語言分配給通訊端的‘原裝’網路資料交換函數:send()、recv()。
(這兩個函數對UDP協議的作用很大,但對TCP來說其實只能說是等於syswrite()、sysread()。)

======================================================================
位元組變數=send(通訊端,傳送資料變數,標誌參數);

send()函數用於在通訊端進程中發送資料。

send()返回的值是儲存所發送的位元組大小值的變數;傳送資料變數為傳輸資料的內容;
標誌參數為0(預設值就可以了)。

例子:$bytes=send(SOCK,$data,0);

======================================================================
地址變數=recv(通訊端,接收後的資料所儲存的變數,接收資料的長度,標誌參數);

recv()函數用於在通訊端進程中接收資料。

recv()返回遠程主機的地址變數;第二個參數為接收後的資料所儲存的變數;第三個
參數為所接收資料的長度;標誌參數同樣為預設值0就可以了。

例子:$address=recv(SOCK,$buffer,$length,0);

======================================================================
實驗1

#!usr/bin/perl
#用戶端
use IO::Handle;
use Socket;
$port=80;
$host='localhost';
$packhost=inet_aton($host);
$address=sockaddr_in($port,$packhost);
socket(CLIENT,AF_INET,SOCK_STREAM,6);
connect(CLIENT,$address);
CLIENT->autoflush(1);
recv(CLIENT,$msg_in,length($msg_in),0);
print "IN:$msg_in/n";
close CLIENT;
exit 1;
=======================================================================
#!usr/bin/perl
#服務端
use IO::Handle;
use Socket;
$port=80;
$host='localhost';
$packhost=inet_aton($host);
$address=sockaddr_in($port,$packhost);
socket(SERVER,AF_INET,SOCK_STREAM,getprotobyname('tcp'));
bind(SERVER,$address);
listen(SERVER,10);
while(1){
next unless (accept(CLIENT,SERVER));
CLIENT->autoflush(1);
$msg_out="WHAT DO YOU WANT?/n";
send(CLIENT,$msg_out,0);
close CLIENT;}
close SERVER;
exit 1;

[日記文]udp of perl socket[perl_sock 3]

writer:demonalex
email:demonalex_at_dark2s.org

繼續上文談到的send()與recv(),這次談一下它們在udp socket中的應用以及如果使用
perl socket API來調用UDP。

先看看在UDP中的send()、recv()應用:
==========================================================================
位元組變數=send(通訊端,傳送資料變數,標誌參數,發送地址);

send()函數用於在通訊端進程中發送資料。

send()返回的值是儲存所發送的位元組大小值的變數;傳送資料變數為傳輸資料的內容;
標誌參數為0(預設值就可以了);send()在udp中就多了最後一個參數,‘發送地址’,
此地址的資料形式為sockaddr_in格式,表示把第二參數‘傳送資料變數’發送到此地址中。

例子:$bytes=send(SOCK,$data,0,$address);
樓上例子中的$address為sockaddr_in格式。
==========================================================================
地址變數=recv(通訊端,接收後的資料所儲存的變數,接收資料的長度,標誌參數);

recv()函數用於在通訊端進程中接收資料。

recv()返回遠程主機的地址變數;第二個參數為接收後的資料所儲存的變數;第三個
參數為所接收資料的長度;標誌參數同樣為預設值0就可以了。

例子:$address=recv(SOCK,$buffer,$length,0);
==========================================================================
從樓上的講解可以知道,在UDP調用中send()比TCP調用時多了一個參數,而recv()與在TCP調用時的
使用方法完全一致。

------------------------------------------------------------------------
UDP網路活動順序:

Client(用戶端):
建立通訊端socket()->發送資料send()->接受資料recv()->關閉通訊端close()

Server(服務端):
建立通訊端socket()->綁定地址bind()->接受資料recv()->發送資料send()->關閉通訊端close()
------------------------------------------------------------------------
從樓上的流程不難發現UDP中的用戶端與服務端的不同之處有兩點:1)服務端在建立通訊端後多添了一個
綁定bind()程式,用於使用戶端能分辨出服務端的網路地址與連接埠;2)在send()與recv()步驟上順序倒過
來了。
〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
最後可以看看例子,琢磨琢磨:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
#!use/bin/perl -w
#udp client
use Socket; #匯入Socket庫
$host=$ARGV[0]; #第一參數為主機變數
$port=$ARGV[1]; #第二參數為連接埠變數
$packhost=inet_aton($host); #壓縮主機地址
$address=sockaddr_in($port,$packhost); #壓為sockaddr_in模式
socket(CLIENT,AF_INET,SOCK_DGRAM,17); #建立UDP通訊端
send(CLIENT,"hi,body!/n",0,$address); #向通訊端發送字串變數
recv(CLIENT,$buff,100,0); #接收資料
print"$buff/n"; #把接收後的資料打入STDOUT
close CLIENT; #關閉通訊端
exit 1; #退出程式
¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#!use/bin/perl -w
#udp server
use Socket; #匯入Socket庫
$localhost=sockaddr_in(4000,INADDR_ANY);#壓入sockaddr_in模式,使用了全域本地壓縮地址INADDR_ANY保留字
socket(SERVER,AF_INET,SOCK_DGRAM,17); #建立UDP通訊端
bind(SERVER,$localhost); #綁定通訊端
while(1){ #進入伺服器迴圈體
next unless $client=recv(SERVER,$buff,100,0); #如果接收到資料就把資料壓入$buff,保留遠程地址在$client
chop($buff); #減去$buff最後的輸入符號
print "$buff/n"; #在$buff變數打入STDOUT
send(SERVER,"$buff/n",0,$client); #把$buff發送給用戶端
}
close SERVER; #關閉通訊端
exit 1; #退出程式
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[日記文]Summary[perl_sock 4]

writer:demonalex
email:demonalex_at_dark2s.org

此文為前三篇文章的總結文。

tcp的服務端I/O結構體:
-----------------------------------------------
while(1){
next unless (accept(CLIENT,SERVER));
CLIENT->autoflush(1);
print CLIENT "WHAT DO YOU WANT?/n";
close CLIENT;}
-----------------------------------------------
udp的服務端I/O結構體:
-----------------------------------------------
while(1){
next unless $client=recv(SERVER,$buff,100,0);
chop($buff);
print "$buff/n";
send(SERVER,"$buff/n",0,$client);
}
-----------------------------------------------

從上面的執行個體可以看出SERVER的I/O體都是迴圈體,有一特定條件進行迴圈
(我們這裡用了死迴圈while(1)),為了就是使服務端能不停的在監聽。

TCP I/O的特徵就是在accept()中產生一個用戶端的通訊端,所有I/O操作都
在此通訊端中進行,當I/O完成後,先把用戶端的通訊端關閉,最後才在程式
的末端部分關閉服務端的通訊端。

UDP I/O的特徵就是recv()部分,由於在介紹UDP的那篇文中的執行個體為通過UDP
把輸入的資料返回到用戶端的程式,在服務端中的下一步就應該調用send()了,
在send()中的最後一個參數為sockaddr_in形式地址,又因為在UDP中不能調用
accept(),所以無法得知對方的對象在哪裡,只能通過recv()的傳回值。recv()
的傳回值剛好為對方發送資料的sockaddr_in形式地址。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.