2015-09-22 4 views
5

में मूल नेटवर्क चैट ऐप मैं सीखने के उद्देश्यों के लिए पर्ल में एक बुनियादी नेटवर्क चैट ऐप लिखने की कोशिश कर रहा हूं। मेरे पास वर्तमान में एक सर्वर और क्लाइंट प्रोग्राम है जो लगभग वैसे ही कार्य करता है जैसा मैं चाहता हूं। एकाधिक ग्राहक सर्वर से कनेक्ट हो सकते हैं और इससे संदेश भेज सकते हैं। हालांकि, मुझे सच में यकीन नहीं है कि एक क्लाइंट से दूसरे क्लाइंट में संदेश भेजने के बारे में कैसे जाना है और यहां सही दिशा में धक्का की सराहना होगी। यहां मेरे पास अभी तक कोड है, विचार?पर्ल

नोट: यह नेटवर्किंग का उपयोग करने या उचित परियोजना के लिए पर्ल का उपयोग करने का मेरा पहला प्रयास है, इसलिए इस बारे में कोई अन्य मार्गदर्शन भी सराहना की जाएगी।

chat_server.pl

#!/usr/bin/perl -w 
# chat_server.pl 
use strict; 
use IO::Socket::INET; 

my $port = shift or die "Port required!\n"; 
my $socket = IO::Socket::INET->new(
     LocalPort => $port, 
     Proto  => 'tcp', 
     Listen  => SOMAXCONN 
    ) or die "Can't create socket: $!!\n"; 
my $child; 

print "Listening for clients on $port...\n"; 
REQUEST: 
while(my $client = $socket->accept) { 
    my $addr = gethostbyaddr($client->peeraddr, AF_INET); 
    my $port = $client->peerport; 

    if($child = fork) { 
     print "New connection from $addr:$port\n"; 
     close $client; 
     next REQUEST; 
    } die "fork failed!\n" unless defined $child; 

    while (<$client>) { 
     print "[$addr:$port] says: $_"; 
     print $client "[$addr:$port] says: $_"; 
    } 
} 
close $socket; 

chat_client.pl

#!/usr/bin/perl -w 
# chat_client.pl 
use strict; 
use IO::Socket::INET; 

my $port   = shift or die "No port\n"; 
my $server   = shift or die "No server\n"; 
my $client_socket = IO::Socket::INET->new(
     PeerPort => $port, 
     PeerAddr => $server, 
     Proto  => 'tcp' 
    ) or die "Can't create send socket: $!!\n"; 

my $child; 

if($child = fork) { 
    while(1) { 
     sleep(1); 
     print scalar <$client_socket>; 
    } 
} 

die "fork failed!\n" unless defined $child; 
print "Connected to $server:$port!\n"; 

do { 
    print "> "; 
    print $client_socket $_ if defined $_; 
} while(<STDIN>); 

print "Closing connection"; 
close $client_socket; 
+2

वास्तव में अनुभव के अपने स्तर के लिए बहुत अच्छा है यही कारण है कि।एकमात्र चीज जो मैं सीधे कहूंगा वह यह है कि आपको यह सुनिश्चित करना चाहिए कि आपकी सीखने की सामग्री अद्यतित है। कमांड लाइन या शेबांग लाइन पर '-w' लंबे समय से बेहतर' उपयोग चेतावनियों 'द्वारा अधिग्रहण किया गया है। 'If' – Borodin

उत्तर

1

एक एकल सर्वर से एक एकल ग्राहक भी मुश्किल नहीं है - क्या आप अपने कोड के साथ वहां क्या कर रहे हैं प्रभावी रूप से - 1 से 1 संबंध बना रहा है। आपका fork एड सर्वर विशेष रूप से आपके क्लाइंट से बात कर रहा है।

एकाधिक ग्राहकों के बीच प्रचार (सर्वर के माध्यम से) को प्रसारित करने के लिए जानकारी प्राप्त करने के लिए, आपको थोड़ा और जटिल होना होगा - क्योंकि आपके पास अलग प्रक्रियाएं हैं, इन प्रक्रियाओं को अब एक-दूसरे के साथ संवाद करने की आवश्यकता है। यह एक बड़ा पर्याप्त सवाल है कि इसके बारे में पर्ल दस्तावेज़ का एक संपूर्ण खंड है: perlipc

यह वास्तव में काफी हद तक अपने कोड की जटिलता को बढ़ाने के लिए, क्योंकि आप अपने संचार पर एक 1-से-अनेक संबंध के लिए जा रहे हैं जा रहा है, और वे सभी एसिंक्रोनस रूप से हो रहा हो जाएगा।

सॉकेट आधारित संचार इंटर-प्रोसेस संचार (आईपीसी) का एक रूप है और आप पहले से ही ऐसा कर रहे हैं। लेकिन यहां आपका 'गॉचा' यह है कि आप 1 से 1 कॉमम्स से 1 तक कई कॉम तक जा रहे हैं। आपको प्रसारण करने में सक्षम होना चाहिए, और संचार का यह तरीका विशेष रूप से अच्छी तरह से समर्थन नहीं करता है। How to extract data from Parallel::ForkManager in perl

फिर IO::Select और can_read का उपयोग वहाँ पाइप पर में आ रहा है किसी भी डेटा है कि अगर एसिंक्रोनस रूप से तय करने के लिए: मैं यहाँ कुछ उदाहरण कोड है -

मैं क्या सुझाव है IO::Pipe को देखो है। आप शायद पाइप की एक सरणी की आवश्यकता होगी - ग्राहक प्रति एक - अन्यथा आप समवर्ती सामान ओवरलैपिंग मिल सकता है।

उदाहरण के लिए:

(IO::Pipe से डॉक पेज:

my $pipe = IO::Pipe->new(); 
if($pid = fork()) { # Parent 
     $pipe->reader(); 
     while(<$pipe>) { 
     ... 
     } 
    } 
    elsif(defined $pid) { # Child 
     $pipe->writer(); 
     print $pipe ... 
    } 

दुर्भाग्य से एक मामूली पकड़ लिया यहाँ है - अपने पाइप forking प्रक्रिया द्वारा बनाया जाएगा, लेकिन यह है कि बदले में आप की आवश्यकता होगी इसका मतलब है पाइप की एक सरणी को कैसे संभालें और यह देखने के लिए जांचें कि वे पठनीय हैं या नहीं।

इसका मतलब है कि आप while लूप में बैठकर सॉकेट स्वीकार करने के आसपास नहीं बैठ सकते हैं - तो ब्लॉक, तो आपके पास संदेश कतारबद्ध होंगे संयुक्त राष्ट्र एक और ग्राहक जोड़ता है (जो वास्तव में आप क्या चाहते हो करने के लिए नहीं जा रहा है) टिल। तो अगर आप भी वहाँ कुछ accept पहले के लिए तैयार है कि क्या जांच करने के लिए select फिर से उपयोग करना होगा।

+0

से पहले,' ईमानदार 'होने के तुरंत बाद,' ई'' के अंदर सर्वर कोड में आपको '$ child' घोषित करना चाहिए, ईमानदार होने के लिए, मैं अभी भी इसे कार्यान्वित करने के बारे में बेहद उलझन में हूं। क्या मैं अभी भी प्रति कनेक्शन केवल एक प्रक्रिया के साथ ऐसा कर सकता हूं या फिर मुझे फिर से फोर्क करने की आवश्यकता होगी? मैं एक कनेक्शन से सभी खुले कनेक्शन में प्राप्त डेटा पैकेट कैसे प्राप्त कर सकता हूं? हालांकि मुझे एक विचार था; कहें कि मेरे पास प्रत्येक फोर्क प्रक्रिया को डेटा सुनने के लिए, एक बार कुछ डेटा प्राप्त करने के बाद, मैं सभी जीवित कनेक्शन वाली सभी प्रक्रियाओं के बीच साझा की गई सूची का उपयोग कर सकता हूं (हालांकि मुझे यह सुनिश्चित नहीं है कि यह कैसे करना है, या यदि यह भी संभव है), और बस सभी कनेक्शन के माध्यम से लूप और इसे इस तरह भेजें। विचार? –

+0

इसकी तुलना में कठिन लगता है क्योंकि फोर्क के माध्यम से साझाकरण सूचियां कठिन हैं। हालांकि थ्रेड कर सकते हैं। – Sobrique

+0

वही निष्कर्ष आया, क्या आप यहां विस्तार से बता सकते हैं कि मैं यहां धागे का उपयोग कैसे कर सकता हूं? –