() এবং পুনর্নির্মাণ () এবং পাঠানোর () এবং () লেখার মধ্যে পার্থক্য কী?


198

মধ্যে পার্থক্য কি read()এবং recv()এবং তাদের মধ্যবর্তী send()এবং write()পারফরমেন্স, গতি এবং অন্যান্য ব্যবহার পরিপ্রেক্ষিতে সকেট প্রোগ্রামিং?


3
ভালো বাস্তবায়িত যেমন লেখার চিন্তা করুন: #define write(...) send(##__VA_ARGS__, 0)
সাবধান 1

উত্তর:


128

পার্থক্যটি হ'ল recv()/ send()কেবল সকেট বর্ণনাকারীর উপর কাজ করে এবং আপনাকে প্রকৃত ক্রিয়াকলাপের জন্য নির্দিষ্ট বিকল্পগুলি নির্দিষ্ট করতে দেয়। এই ফাংশনগুলি কিছুটা বেশি বিশেষায়িত (উদাহরণস্বরূপ, আপনি অগ্রাহ্য করার জন্য SIGPIPE, বা ব্যান্ড-আউট-ব্যান্ড বার্তা প্রেরণে একটি পতাকা সেট করতে পারেন ...)।

কার্যাবলী read()/ write()হয় সার্বজনীন ফাইল বর্ণনাকারী সব বর্ণনাকারী কাজ ফাংশন।


3
এটি ভুল, 0 দৈর্ঘ্যের ডেটাগ্রামের ক্ষেত্রে আরও একটি পার্থক্য রয়েছে - যদি শূন্য-দৈর্ঘ্যের ডেটাগ্রামটি মুলতুবি থাকে, (2) এবং recv () শূন্যের পতাকা যুক্তি সহ বিভিন্ন আচরণ সরবরাহ করে read এই পরিস্থিতিতে, পড়ুন (2) এর কোনও প্রভাব নেই (ডেটাগ্রামটি মুলতুবি রয়েছে), যখন recv () মুলতুবি থাকা ডেটাগ্রাম গ্রাস করে।
অভিনব গৌনিয়াল

2
@ অভিনবগৌনিয়াল কীভাবে এটি ভিন্ন আচরণ প্রদান করবে ? যদি 0 বাইট ডেটাগ্রাম থাকে তবে উভয়ই, recvএবং readকলারের কাছে কোনও ডেটা সরবরাহ করবে না তবে ত্রুটিও নেই। কলারের জন্য, আচরণটি একই রকম। কলকারী এমনকি ডেটাগ্রাম সম্পর্কে কিছু জানেন না (এটি জানেন না যে এটি একটি সকেট এবং কোনও ফাইল নয়, এটি জানেন না যে এটি কোনও ডেটাগ্রামের সকেট এবং স্ট্রিম সকেট নয়)। ডেটাগ্রামে মুলতুবি থাকার বিষয়টি হ'ল আইপি স্ট্যাকগুলি কার্নেলগুলিতে কীভাবে কাজ করে এবং কলারের কাছে দৃশ্যমান নয় সে সম্পর্কে অন্তর্নিহিত জ্ঞান। কলারের দৃষ্টিকোণ থেকে তারা এখনও সমান আচরণ করবে।
মক্কি

2
@ মেক্কি যা সবার জন্য নিখুঁত জ্ঞান নয়, উদাহরণস্বরূপ আমাকে
ধরুন

1
@ মেক্কি 0 বাইটের অ-ব্লক করা সফল পড়া কী বোঝায়? ডেটাগ্রাম কি এখনও মুলতুবি থাকে? ঠিক এটি এবং কেবল তা-ই আমাকে চিন্তিত করছে: সফলভাবে পড়লেও কোনও ডেটাগ্রামের আচরণটি মুলতুবি থাকতে পারে। আমি পরিস্থিতি উত্থাপিত হতে পারে কিনা তা নিশ্চিত নই, যা আমি এটিকে মাথায় রাখতে চাই।
sehe

2
@ যদি আপনি চিন্তিত হন তবে আপনি কেন ব্যবহার করবেন না recv? প্রথম স্থানটিতে কেন recvএবং sendকোথায় প্রবর্তন করা হয়েছিল তা হ'ল সমস্ত ডেটাগ্রাম ধারণাগুলি স্রোতের জগতে ম্যাপ করা যায় না। readএবং writeতথ্য একটি স্ট্রিম, তা একটি নল, একটি ফাইল, একটি ডিভাইস (যেমন একটি সিরিয়াল পোর্ট) অথবা একটি সকেট হিসাবে আচরণ সবকিছু। তবুও কোনও সকেট কেবল আসল স্ট্রিম যদি এটি টিসিপি ব্যবহার করে। যদি এটি ইউডিপি ব্যবহার করে তবে এটি একটি ব্লক ডিভাইসের মতো। তবে উভয় পক্ষ যদি এটি স্ট্রিমের মতো ব্যবহার করে তবে এটি স্রোতের মতো কাজ করবে এবং আপনি writeকল ব্যবহার করে খালি ইউডিপি প্যাকেটটি পাঠাতেও পারবেন না , সুতরাং এই পরিস্থিতি তৈরি হবে না।
মেকি

85

গুগলে প্রথম হিট প্রতি

পঠন () 0 এর পতাকা প্যারামিটার সহ recv () এর সমতুল্য, পতাকাগুলির প্যারামিটারের জন্য অন্যান্য মানগুলি rec () এর আচরণ পরিবর্তন করে। একইভাবে, লিখুন () পতাকাগুলি == 0 পাঠানোর সমতুল্য।


31
এটি পুরো গল্প নয়। recvকেবলমাত্র সকেটে ব্যবহার করা যেতে পারে এবং আপনি যদি এটি ব্যবহার করার চেষ্টা করেন, বলুন, ত্রুটি তৈরি করবে STDIN_FILENO
জোয় অ্যাডামস

76
এই থ্রেডটি এখন গুগলে প্রথম হিট, গুগল স্ট্যাকওভারফ্লো পছন্দ করে
এলওফ

12

read()এবং write()আরও জেনেরিক, তারা কোনও ফাইল বর্ণনাকারীর সাথে কাজ করে। তবে তারা উইন্ডোজে কাজ করবে না।

আপনি অতিরিক্ত বিকল্পগুলি পাস করতে পারেন send()এবং recv()তাই আপনাকে কিছু ক্ষেত্রে এগুলি ব্যবহার করতে হতে পারে।


7

আমি সম্প্রতি লক্ষ্য করেছি যে আমি যখন write()উইন্ডোজের সকেটে ব্যবহার করতাম , তখন এটি প্রায় কাজ করে (এফডিটি পাসের মতো write()হয় না send(); আমি _open_osfhandle()এফডি পাস করার জন্য ব্যবহার করতাম write())। যাইহোক, আমি যখন বাইনারি ডেটা প্রেরণের চেষ্টা করছিলাম তখন এটি কার্যকর হয়নি 10 অক্ষর অন্তর্ভুক্ত write()যেখানে কোথাও এর আগে 13 টি অক্ষর characterোকানো হয়েছিল। send()0 এর ফ্ল্যাগ প্যারামিটার দিয়ে এটিকে পরিবর্তন করা সমস্যার সমাধান করে। read()বাইনারি ডেটাতে 13-10 ধারাবাহিকভাবে থাকলে বিপরীত সমস্যা হতে পারে তবে আমি এটি পরীক্ষা করিনি। তবে এটি send()এবং এর মধ্যে আরেকটি সম্ভাব্য পার্থক্য বলে মনে হয় write()


2
+1 টি। আরও দেখুন উইনসক পড়া /
লেখাকে

6

লিনাক্সের আরেকটি জিনিস হ'ল:

sendনন-সকেট এফডি চালানোর অনুমতি দেয় না। সুতরাং, উদাহরণস্বরূপ ইউএসবি পোর্টে লিখতে, writeপ্রয়োজনীয় is


3

"পারফরম্যান্স এবং গতি"? এখানে কি এই জাতীয় শব্দ নয়?

যাইহোক, recv()কলটি এমন পতাকা নেয় read()যা তা দেয় না, এটি এটিকে আরও শক্তিশালী বা কমপক্ষে আরও সুবিধাজনক করে তোলে। এটি একটি পার্থক্য। আমি মনে করি না পার্শ্ববর্তী পারফরম্যান্সের একটি উল্লেখযোগ্য পার্থক্য রয়েছে, তবে এটির জন্য পরীক্ষা করা হয়নি।


15
সম্ভবত পতাকা মোকাবেলা না করাকে আরও সুবিধাজনক বলে মনে করা যেতে পারে।
সেমজ

2

লিনাক্সে আমি এটিও লক্ষ্য করেছি:

সিগন্যাল হ্যান্ডলারদের দ্বারা সিস্টেম কল এবং লাইব্রেরি ফাংশনগুলিতে বাধা
যদি কোনও সিস্টেম কল বা লাইব্রেরি ফাংশন কলটি অবরুদ্ধ অবস্থায় একটি সিগন্যাল হ্যান্ডলার আহ্বান করা হয়, তবে হয়:

  • সিগন্যাল হ্যান্ডলার ফিরে আসার পরে কলটি স্বয়ংক্রিয়ভাবে পুনরায় শুরু হয়; অথবা

  • EINTR ত্রুটির সাথে কলটি ব্যর্থ হয়।

... বিস্তারিত ইউনিক্স সিস্টেম জুড়ে বিভিন্ন; নীচে, লিনাক্সের জন্য বিশদ।

যদি নিম্নলিখিত কোনও ইন্টারফেসে একটি অবরুদ্ধ কল যদি একটি সিগন্যাল হ্যান্ডলার দ্বারা বাধা দেয়, তবে SA_RESTART পতাকা ব্যবহার করা হলে সিগন্যাল হ্যান্ডলারটি ফিরে আসার পরে কলটি স্বয়ংক্রিয়ভাবে পুনরায় শুরু হয়; অন্যথায় কলটি ত্রুটি EINTR এর সাথে ব্যর্থ হয়:

  • পড়া (2), readv (2), লেখ (2), writev (2), ও ioctl (2) "ধীর" ডিভাইসের কল।

.....

সিএআলএসএলএসটিআরটির ব্যবহার ব্যতীত নিম্নলিখিত ইন্টারফেসগুলি সিগন্যাল হ্যান্ডলার দ্বারা বাধা দেওয়ার পরে পুনরায় আরম্ভ করা হবে না; সিগন্যাল হ্যান্ডলার দ্বারা বাধা দেওয়া হলে তারা সর্বদা ত্রুটি EINTR নিয়ে ব্যর্থ হয়:

  • "ইনপুট" সকেট ইন্টারফেসগুলি যখন সকেটে সেটসকোপ্ট (2) ব্যবহার করে টাইমআউট (SO_RCVTIMEO) সেট করা থাকে: গ্রহণ করুন (2), recv (2), recvfrom (2), recvmmsg (2) (একটি নন-নুলের সাথেও সময়সীমা আর্গুমেন্ট), এবং recvmsg (2)।

  • "আউটপুট" সকেট ইন্টারফেসগুলি যখন সকেটে সেটসকোপ্ট (2) ব্যবহার করে সকেটে একটি টাইমআউট (SO_RCVTIMEO) সেট করা থাকে: সংযোগ (2), প্রেরণ (2), সেন্ডো (2), এবং সেন্ডসএমজি (2)।

man 7 signalআরও বিশদ জন্য পরীক্ষা করুন।


recvfromঅনির্দিষ্টকালের জন্য অবরুদ্ধ হওয়া এড়াতে একটি সাধারণ ব্যবহার হ'ল ব্যবহারের সংকেত ।

এপিইউ থেকে একটি উদাহরণ :

#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>

#define BUFLEN      128
#define TIMEOUT     20

void
sigalrm(int signo)
{
}

void
print_uptime(int sockfd, struct addrinfo *aip)
{
    int     n;
    char    buf[BUFLEN];

    buf[0] = 0;
    if (sendto(sockfd, buf, 1, 0, aip->ai_addr, aip->ai_addrlen) < 0)
        err_sys("sendto error");
    alarm(TIMEOUT);
    //here
    if ((n = recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL)) < 0) {
        if (errno != EINTR)
            alarm(0);
        err_sys("recv error");
    }
    alarm(0);
    write(STDOUT_FILENO, buf, n);
}

int
main(int argc, char *argv[])
{
    struct addrinfo     *ailist, *aip;
    struct addrinfo     hint;
    int                 sockfd, err;
    struct sigaction    sa;

    if (argc != 2)
        err_quit("usage: ruptime hostname");
    sa.sa_handler = sigalrm;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIGALRM, &sa, NULL) < 0)
        err_sys("sigaction error");
    memset(&hint, 0, sizeof(hint));
    hint.ai_socktype = SOCK_DGRAM;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)
        err_quit("getaddrinfo error: %s", gai_strerror(err));

    for (aip = ailist; aip != NULL; aip = aip->ai_next) {
        if ((sockfd = socket(aip->ai_family, SOCK_DGRAM, 0)) < 0) {
            err = errno;
        } else {
            print_uptime(sockfd, aip);
            exit(0);
        }
    }

    fprintf(stderr, "can't contact %s: %s\n", argv[1], strerror(err));
    exit(1);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.