Erlang 21

gen_tcp




erlang

gen_tcp

मॉड्यूल

gen_tcp

मॉड्यूल सारांश

टीसीपी / आईपी सॉकेट्स को इंटरफ़ेस।

विवरण

यह मॉड्यूल टीसीपी / आईपी प्रोटोकॉल का उपयोग करके सॉकेट के साथ संचार करने के लिए कार्य प्रदान करता है।

निम्न कोड टुकड़ा पोर्ट 5678 पर एक सर्वर से कनेक्ट करने वाले एक ग्राहक का एक सरल उदाहरण है, एक बाइनरी को स्थानांतरित करना और कनेक्शन को बंद करना:

client() ->
    SomeHostInNet = "localhost", % to make it runnable on one machine
    {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678, 
                                 [binary, {packet, 0}]),
    ok = gen_tcp:send(Sock, "Some Data"),
    ok = gen_tcp:close(Sock).

दूसरे छोर पर, एक सर्वर पोर्ट 5678 पर सुन रहा है, कनेक्शन स्वीकार करता है, और बाइनरी प्राप्त करता है:

server() ->
    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0}, 
                                        {active, false}]),
    {ok, Sock} = gen_tcp:accept(LSock),
    {ok, Bin} = do_recv(Sock, []),
    ok = gen_tcp:close(Sock),
    ok = gen_tcp:close(LSock),
    Bin.

do_recv(Sock, Bs) ->
    case gen_tcp:recv(Sock, 0) of
        {ok, B} ->
            do_recv(Sock, [Bs, B]);
        {error, closed} ->
            {ok, list_to_binary(Bs)}
    end.

अधिक उदाहरणों के लिए, अनुभाग Examples देखें।

जानकारी का प्रकार

option() =
{active, true | false | once | -32768..32767} |
{buffer, integer() >= 0} |
{delay_send, boolean()} |
{deliver, port | term} |
{dontroute, boolean()} |
{exit_on_close, boolean()} |
{header, integer() >= 0} |
{high_msgq_watermark, integer() >= 1} |
{high_watermark, integer() >= 0} |
{keepalive, boolean()} |
{linger, {boolean(), integer() >= 0}} |
{low_msgq_watermark, integer() >= 1} |
{low_watermark, integer() >= 0} |
{mode, list | binary} |
list |
binary |
{nodelay, boolean()} |
{packet,
0 |
1 |
2 |
4 |
raw |
sunrm |
asn1 |
cdr |
fcgi |
line |
tpkt |
http |
httph |
http_bin |
httph_bin} |
{packet_size, integer() >= 0} |
{priority, integer() >= 0} |
{raw,
Protocol :: integer() >= 0,
OptionNum :: integer() >= 0,
ValueBin :: binary()} |
{recbuf, integer() >= 0} |
{reuseaddr, boolean()} |
{send_timeout, integer() >= 0 | infinity} |
{send_timeout_close, boolean()} |
{show_econnreset, boolean()} |
{sndbuf, integer() >= 0} |
{tos, integer() >= 0} |
{ipv6_v6only, boolean()}

option_name() =
active |
buffer |
delay_send |
deliver |
dontroute |
exit_on_close |
header |
high_msgq_watermark |
high_watermark |
keepalive |
linger |
low_msgq_watermark |
low_watermark |
mode |
nodelay |
packet |
packet_size |
priority |
{raw,
Protocol :: integer() >= 0,
OptionNum :: integer() >= 0,
ValueSpec ::
(ValueSize :: integer() >= 0) | (ValueBin :: binary())} |
recbuf |
reuseaddr |
send_timeout |
send_timeout_close |
show_econnreset |
sndbuf |
tos |
ipv6_v6only

connect_option() =
{ip, inet:socket_address() } |
{fd, Fd :: integer() >= 0} |
{ifaddr, inet:socket_address() } |
inet:address_family() |
{port, inet:port_number() } |
{tcp_module, module()} |
{netns, file:filename_all() } |
{bind_to_device, binary()} |
option()

listen_option() =
{ip, inet:socket_address() } |
{fd, Fd :: integer() >= 0} |
{ifaddr, inet:socket_address() } |
inet:address_family() |
{port, inet:port_number() } |
{backlog, B :: integer() >= 0} |
{tcp_module, module()} |
{netns, file:filename_all() } |
{bind_to_device, binary()} |
option()

सॉकेट ()

जैसा कि accept/1,2 और connect/3,4 द्वारा लौटाया गया।

निर्यात

स्वीकार करें (ListenSocket) -> {ठीक है, सॉकेट} | {त्रुटि, कारण}
स्वीकार करें (ListenSocket, Timeout) -> {ठीक है, सॉकेट} | {त्रुटि, कारण}

प्रकार

listen/2 लौटा listen/2

एक सुनने वाले सॉकेट पर आने वाले कनेक्शन अनुरोध को स्वीकार करता है। Socket को listen/2 से लौटाया गया Socket होना चाहिए। Timeout मिलीसेकंड में टाइम-आउट मान निर्दिष्ट करता है। infinity

यह दिखाता है:

  • {ok, Socket} यदि कोई कनेक्शन स्थापित है

  • {error, closed} यदि ListenSocket बंद है

  • {error, timeout} यदि निर्दिष्ट समय के भीतर कोई कनेक्शन स्थापित नहीं है

  • {error, system_limit} यदि {error, system_limit} एमुलेटर में सभी उपलब्ध पोर्ट उपयोग में हैं

  • POSIX त्रुटि मान यदि कुछ और गलत हो जाता है, तो संभावित त्रुटि मानों के लिए inet(3) देखें

पैकेट भेजे गए send/2 का उपयोग करके लौटे सॉकेट Socket भेजा जा सकता है। सहकर्मी से भेजे गए पैकेट संदेश के रूप में वितरित किए जाते हैं (जब तक कि {active, false} को सुनने वाले सॉकेट के लिए विकल्प सूची में निर्दिष्ट नहीं किया जाता है, जिस स्थिति में पैकेट को recv/2 कहकर पुनर्प्राप्त किया जाता है):

{tcp, Socket, Data}
ध्यान दें

accept कॉल को सॉकेट स्वामी प्रक्रिया से जारी करने की आवश्यकता नहीं है। संस्करण 5.5.3 और एमुलेटर के उच्चतर का उपयोग करते हुए, विभिन्न प्रक्रियाओं से एक साथ कई कॉल स्वीकार किए जा सकते हैं, जो आने वाले कनेक्शन को संभालने वाले स्वीकर्ता प्रक्रियाओं के पूल के लिए अनुमति देता है।

बंद (सॉकेट) -> ठीक है

प्रकार

एक टीसीपी सॉकेट बंद कर देता है।

ध्यान दें कि टीसीपी के अधिकांश कार्यान्वयन में, एक close यह गारंटी नहीं देता है कि भेजे गए किसी भी डेटा को दूरस्थ पक्ष में पता चलने से पहले प्राप्तकर्ता को वितरित किया जाता है। यदि आप प्राप्तकर्ता को डेटा की डिलीवरी की गारंटी देना चाहते हैं तो इसे प्राप्त करने के दो सामान्य तरीके हैं।

  • gen_tcp:shutdown(Sock, write) उपयोग करें gen_tcp:shutdown(Sock, write) यह संकेत देने के लिए कि कोई और डेटा नहीं भेजा जाना है और सॉकेट के रीड साइड के बंद होने की प्रतीक्षा करें।

  • सॉकेट विकल्प का उपयोग करें {packet, N} (या कुछ इसी तरह) यह संभव है कि रिसीवर के लिए कनेक्शन को बंद करने के लिए जब यह पता चले कि यह सभी डेटा प्राप्त कर चुका है।

कनेक्ट (पता, पोर्ट, विकल्प) -> {ठीक है, सॉकेट} | {त्रुटि, कारण}
कनेक्ट (पता, पोर्ट, विकल्प, टाइमआउट) ->
{ठीक है, सॉकेट} | {त्रुटि, कारण}

प्रकार

IP पते के साथ होस्ट पर TCP पोर्ट Port पर एक सर्वर से जुड़ता है। तर्क Address होस्टनाम या IP Address हो सकता है।

निम्न विकल्प उपलब्ध हैं:

{ip, Address}

यदि होस्ट में कई नेटवर्क इंटरफेस हैं, तो यह विकल्प निर्दिष्ट करता है कि किसका उपयोग करना है।

{ifaddr, Address}

{ip, Address} समान। यदि होस्ट में कई नेटवर्क इंटरफेस हैं, तो यह विकल्प निर्दिष्ट करता है कि किसका उपयोग करना है।

{fd, integer() >= 0}

यदि कोई सॉकेट gen_tcp का उपयोग किए बिना किसी तरह से कनेक्ट किया गया है, तो इसके लिए फ़ाइल डिस्क्रिप्टर पास करने के लिए इस विकल्प का उपयोग करें। यदि {ip, Address} और / या {port, port_number()} को इस विकल्प के साथ जोड़ दिया जाता है, तो fd कनेक्ट होने से पहले निर्दिष्ट इंटरफ़ेस और पोर्ट से बंध जाता है। यदि ये विकल्प निर्दिष्ट नहीं हैं, तो यह माना जाता है कि fd पहले से ही उचित रूप से बंधा हुआ है।

inet

IPv4 के लिए सॉकेट सेट करता है।

inet6

IPv6 के लिए सॉकेट सेट करता है।

local

एक यूनिक्स डोमेन सॉकेट सेट करता है। inet:local_address() देखें inet:local_address()

{port, Port}

निर्दिष्ट करता है कि किस स्थानीय पोर्ट नंबर का उपयोग करना है।

{tcp_module, module()}

ओवरराइड जो कॉलबैक मॉड्यूल का उपयोग किया जाता है। IPv4 के लिए inet_tcp और IPv6 के लिए inet6_tcp

Opt

inet:setopts/2 देखें inet:setopts/2

पैकेट भेजे गए send/2 का उपयोग करके लौटे सॉकेट Socket भेजा जा सकता है। सहकर्मी से भेजे गए पैकेट संदेश के रूप में दिए गए हैं:

{tcp, Socket, Data}

यदि सॉकेट {active, N} मोड में है (विवरण के लिए inet:setopts/2 देखें) और इसका संदेश काउंटर 0 गिरता है, तो निम्न संदेश यह इंगित करने के लिए दिया जाता है कि सॉकेट ने निष्क्रिय ( {active, false} ) में संक्रमण किया है। मोड:

{tcp_passive, Socket}

यदि सॉकेट बंद है, तो निम्न संदेश दिया जाता है:

{tcp_closed, Socket}

यदि सॉकेट पर कोई त्रुटि होती है, तो निम्न संदेश दिया जाता है (जब तक कि {active, false} सॉकेट के लिए विकल्प सूची में निर्दिष्ट नहीं किया जाता है, जिस स्थिति में पैकेट को recv/2 कहकर पुनर्प्राप्त किया जाता है):

{tcp_error, Socket, Reason}

वैकल्पिक Timeout पैरामीटर मिलीसेकंड में टाइम-आउट निर्दिष्ट करता है। infinity

ध्यान दें

connect करने के connect निर्दिष्ट विकल्पों के लिए डिफ़ॉल्ट मान कर्नेल कॉन्फ़िगरेशन पैरामीटर inet_default_connect_options प्रभावित हो सकते हैं। विवरण के लिए, inet(3)

control_process (सॉकेट, पीआईडी) -> ठीक | {त्रुटि, कारण}

प्रकार

सॉकेट के लिए एक नई नियंत्रण प्रक्रिया को असाइन करता है। नियंत्रण प्रक्रिया वह प्रक्रिया है जो सॉकेट से संदेश प्राप्त करती है। यदि वर्तमान नियंत्रण प्रक्रिया की तुलना में किसी अन्य प्रक्रिया द्वारा बुलाया जाता है, तो {error, not_owner} वापस कर दिया जाता है। यदि Pid द्वारा पहचानी गई प्रक्रिया कोई मौजूदा स्थानीय pid नहीं है, तो {error, badarg} वापस कर दिया जाता है। {error, badarg} कुछ मामलों में भी लौटाया जा सकता है जब इस फ़ंक्शन के निष्पादन के दौरान Socket बंद हो जाता है।

यदि सॉकेट सक्रिय मोड में सेट है, तो यह फ़ंक्शन कॉलर के मेलबॉक्स में किसी भी संदेश को नई नियंत्रण प्रक्रिया में स्थानांतरित कर देगा। यदि स्थानांतरण के दौरान कोई अन्य प्रक्रिया सॉकेट के साथ सहभागिता कर रही है, तो स्थानांतरण सही ढंग से काम नहीं कर सकता है और कॉल करने वाले के मेलबॉक्स में संदेश रह सकते हैं। उदाहरण के लिए, ट्रांसफ़ेयर पूरा होने से पहले सॉकेट्स को सक्रिय मोड में बदलना इसके कारण हो सकता है।

सुनो (पोर्ट, विकल्प) -> {ठीक है, ListenSocket} | {त्रुटि, कारण}

प्रकार

स्थानीय होस्ट पर पोर्ट Port को सुनने के लिए एक सॉकेट स्थापित करता है।

यदि Port == 0 , अंतर्निहित ओएस एक उपलब्ध पोर्ट नंबर प्रदान करता है, तो इसे पुनः प्राप्त करने के लिए inet:port/1 का उपयोग करें।

निम्न विकल्प उपलब्ध हैं:

list

प्राप्त Packet को एक सूची के रूप में वितरित किया जाता है।

binary

प्राप्त Packet को बाइनरी के रूप में वितरित किया जाता है।

{backlog, B}

B एक पूर्णांक है = = 0 । बैकलॉग मान अधिकतम लंबाई को परिभाषित करता है कि लंबित कनेक्शन की कतार बढ़ सकती है। 5 चूक।

{ip, Address}

यदि होस्ट में कई नेटवर्क इंटरफ़ेस हैं, तो यह विकल्प निर्दिष्ट करता है कि किस पर सुनना है।

{port, Port}

निर्दिष्ट करता है कि किस स्थानीय पोर्ट नंबर का उपयोग करना है।

{fd, Fd}

यदि कोई सॉकेट gen_tcp का उपयोग किए बिना किसी तरह से कनेक्ट किया गया है, तो इसके लिए फ़ाइल डिस्क्रिप्टर पास करने के लिए इस विकल्प का उपयोग करें।

{ifaddr, Address}

{ip, Address} समान। यदि होस्ट में कई नेटवर्क इंटरफेस हैं, तो यह विकल्प निर्दिष्ट करता है कि किसका उपयोग करना है।

inet6

IPv6 के लिए सॉकेट सेट करता है।

inet

IPv4 के लिए सॉकेट सेट करता है।

{tcp_module, module()}

ओवरराइड जो कॉलबैक मॉड्यूल का उपयोग किया जाता है। IPv4 के लिए inet_tcp और IPv6 के लिए inet6_tcp

Opt

inet:setopts/2 देखें inet:setopts/2

आने वाले कनेक्शन अनुरोधों को स्वीकार करने के लिए accept/1,2 को कॉल करने के लिए कॉल किए गए ListenSocket का उपयोग किया जाना चाहिए।

ध्यान दें

listen लिए निर्दिष्ट विकल्पों के लिए डिफ़ॉल्ट मान कर्नेल कॉन्फ़िगरेशन पैरामीटर inet_default_listen_options प्रभावित हो सकते हैं। विवरण के लिए, inet(3)

recv (सॉकेट, लंबाई) -> {ठीक है, पैकेट} | {त्रुटि, कारण}
recv (सॉकेट, लंबाई, समय समाप्त) -> {ठीक है, पैकेट} | {त्रुटि, कारण}

प्रकार

HttpPacket में HttpPacket का विवरण देखें erlang:decode_packet/3 ERTS में erlang:decode_packet/3

निष्क्रिय मोड में एक सॉकेट से एक पैकेट प्राप्त करता है। एक बंद सॉकेट को रिटर्न वैल्यू {error, closed} द्वारा दर्शाया गया है।

तर्क Length केवल सार्थक है जब सॉकेट raw मोड में है और पढ़ने के लिए बाइट्स की संख्या को दर्शाता है। यदि Length 0 , तो सभी उपलब्ध बाइट्स वापस आ जाते हैं। यदि Length > 0 , बिल्कुल Length बाइट्स लौटाए जाते हैं, या एक त्रुटि; जब सॉकेट दूसरी तरफ से बंद हो जाता है तो संभवतः डेटा की Length बाइट्स से कम हो जाता है।

वैकल्पिक Timeout पैरामीटर मिलीसेकंड में टाइम-आउट निर्दिष्ट करता है। infinity

send (सॉकेट, पैकेट) -> ठीक है | {त्रुटि, कारण}

प्रकार

एक सॉकेट पर एक पैकेट भेजता है।

यदि टाइम-आउट वांछित हैं, तो टाइम-आउट विकल्प के साथ कोई कॉल कॉल नहीं है, सॉकेट विकल्प send_timeout उपयोग करें। अनुभाग Examples देखें।

शटडाउन (सॉकेट, कैसे) -> ठीक है | {त्रुटि, कारण}

प्रकार

एक या दो दिशाओं में एक सॉकेट बंद कर देता है।

How == write मतलब है लेखन के लिए सॉकेट बंद करना, इससे पढ़ना अभी भी संभव है।

यदि How == read या Socket पोर्ट में कोई निवर्तमान डेटा बफ़र नहीं किया गया है, तो सॉकेट को तुरंत बंद कर दिया जाता है और किसी भी त्रुटि का सामना करना पड़ता है।

यदि सॉकेट पोर्ट में डेटा बफ़र किया गया है, तो सॉकेट को बंद करने का प्रयास तब तक के लिए स्थगित कर दिया जाता है जब तक कि डेटा को कर्नेल सॉकेट को बफर में न लिखा जाए। यदि किसी भी त्रुटि का सामना करना पड़ता है, तो सॉकेट बंद हो जाता है और {error, closed} अगले recv/2 पर वापस आ जाता है या send/2

यदि पीयर ने राइट साइड पर शटडाउन किया है तो विकल्प {exit_on_close, false} उपयोगी है।

उदाहरण

निम्न उदाहरण {active,once} श्रवण सॉकेट पर स्वीकार करते हुए कई सर्वर प्रक्रियाओं के रूप में एक सर्वर को लागू करके विकल्प {active,once} और एकाधिक स्वीकार के उपयोग को दिखाता है। फ़ंक्शन start/2 कार्यकर्ता प्रक्रियाओं की संख्या और आने वाले कनेक्शनों को सुनने के लिए पोर्ट नंबर लेता है। अगर LPort को 0 रूप में निर्दिष्ट किया जाता है, तो एक LPort पोर्ट नंबर का उपयोग किया जाता है, यही वजह है कि प्रारंभ फ़ंक्शन आवंटित किए गए वास्तविक पोर्ट नंबर को लौटाता है:

start(Num,LPort) ->
    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
        {ok, ListenSock} ->
            start_servers(Num,ListenSock),
            {ok, Port} = inet:port(ListenSock),
            Port;
        {error,Reason} ->
            {error,Reason}
    end.

start_servers(0,_) ->
    ok;
start_servers(Num,LS) ->
    spawn(?MODULE,server,[LS]),
    start_servers(Num-1,LS).

server(LS) ->
    case gen_tcp:accept(LS) of
        {ok,S} ->
            loop(S),
            server(LS);
        Other ->
            io:format("accept returned ~w - goodbye!~n",[Other]),
            ok
    end.

loop(S) ->
    inet:setopts(S,[{active,once}]),
    receive
        {tcp,S,Data} ->
            Answer = process(Data), % Not implemented in this example
            gen_tcp:send(S,Answer),
            loop(S);
        {tcp_closed,S} ->
            io:format("Socket ~w closed [~w]~n",[S,self()]),
            ok
    end.

एक साधारण ग्राहक का उदाहरण:

client(PortNo,Message) ->
    {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
                                                    {packet,2}]),
    gen_tcp:send(Sock,Message),
    A = gen_tcp:recv(Sock,0),
    gen_tcp:close(Sock),
    A.

send कॉल समय-आउट विकल्प को स्वीकार नहीं करता है क्योंकि भेजने पर समय-आउट सॉकेट विकल्प send_timeout माध्यम से नियंत्रित किया जाता है। बिना रिसीवर के साथ सेंड ऑपरेशन का व्यवहार मुख्य रूप से अंतर्निहित टीसीपी स्टैक और नेटवर्क इन्फ्रास्ट्रक्चर द्वारा परिभाषित किया गया है। कोड लिखने के लिए जो एक हैंगिंग रिसीवर को हैंडल करता है जो आखिरकार send को निम्न की तरह send पर लटकने का कारण बन सकता है।

उस प्रक्रिया पर विचार करें जो क्लाइंट प्रक्रिया से डेटा प्राप्त करता है जिसे नेटवर्क पर सर्वर को भेजा जाना है। प्रक्रिया टीसीपी / आईपी के माध्यम से सर्वर से जुड़ी हुई है और इसे भेजे जाने वाले प्रत्येक संदेश के लिए कोई भी पावती नहीं मिलती है, लेकिन दूसरे छोर के गैर-जिम्मेदार होने का पता लगाने के लिए भेजने के समय के विकल्प पर निर्भर रहना पड़ता है। कनेक्ट करते समय विकल्प send_timeout का उपयोग किया जा सकता है:

...
{ok,Sock} = gen_tcp:connect(HostAddress, Port,
                            [{active,false},
                             {send_timeout, 5000},
                             {packet,2}]),
                loop(Sock), % See below
...

लूप में जहां अनुरोधों को संभाला जाता है, समय-आउट भेजें अब पता लगाया जा सकता है:

loop(Sock) ->
    receive
        {Client, send_data, Binary} ->
            case gen_tcp:send(Sock,[Binary]) of
                {error, timeout} ->
                    io:format("Send timeout, closing!~n",
                              []),
                    handle_send_timeout(), % Not implemented here
                    Client ! {self(),{error_sending, timeout}},
                    %% Usually, it's a good idea to give up in case of a 
                    %% send timeout, as you never know how much actually 
                    %% reached the server, maybe only a packet header?!
                    gen_tcp:close(Sock);
                {error, OtherSendError} ->
                    io:format("Some other error on socket (~p), closing",
                              [OtherSendError]),
                    Client ! {self(),{error_sending, OtherSendError}},
                    gen_tcp:close(Sock);
                ok ->
                    Client ! {self(), data_sent},
                    loop(Sock)
            end
    end.

आमतौर पर यह प्राप्त करने के समय-समय का पता लगाने के लिए पर्याप्त होता है, क्योंकि अधिकांश प्रोटोकॉल में सर्वर से किसी प्रकार की पावती शामिल होती है, लेकिन यदि प्रोटोकॉल कड़ाई से एक तरीका है, तो विकल्प send_timeout सामने आता है।