1 / 31

ادامه فصل 7

ادامه فصل 7. توابع مفید دربرنامه نویسی شبکه:.

lydia-mccoy
Download Presentation

ادامه فصل 7

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ادامه فصل 7

  2. توابع مفید دربرنامه نویسی شبکه: • تابعGetpeername( ) : بااستفاده ازاین تابع میتوانید هویت طرف مقابل(شامل آدرس IPوآدرس پورت پروسه طرف مقابل ارتباط)را استخراج نمایید.پارامترهای تابع: #include <sys/socket.h> int getpeername(int sockfd, struct sockaddr *addr, int *addrlen ) • Sockfd:مشخصه سوکت مورد نظر • Addr:استراکچری است ازنوع sockaddr که توسطه سیستم عامل باآدرس IPوآدرس پورت طرف مقابل پرخواهد شد • addrlen:طول استراکچر sockaddr

  3. در صورت موفقیت آمیز نبودن اجرای تابع،مقدار برگشتی (1-) خواهد بود ودر متغیر سراسری errno شماره خطا برای بررسی نوع و ماهیت خطا،تنظیم خواهد شد.

  4. تابعGethostname( ): این تابع نام ماشینی راکه برنامه شماروی آن اجرامیشود برخواهدگرداند.این نام یک رشته کاراکتری معادل بانام نمادین ماشین است نه آدرس IPآن! #include <unistd.h> Int Gethostname( char *hostname, size_t size); • hostname:یک رشته کاراکتری است که پس از بازگشت تابع,نام ماشین درآن ذخیره میشود. • Size:طول رشته کاراکتر برحسب کاراکتر

  5. اگرمقداربرگشتی(1-) باشد خطایی بروزداده ومقدارerrno شماره خطا را نگه میدارد ولی اگرتابع موفق عمل کند مقداربرگشت صفر خواهد بود.

  6. فراخوانی سیستم DNSبرای ترجمه آدرسهای حوزه: • درمثالهای کوچکی که تااینجا داشتیم همگی برای برقراری یک ارتباط باماشین خاص,مستقیمأ ازآدرس IP استفاده می کردند ولی حالا فرض کنید بخواهید برنامه ای بنویسید که کاربر بتواند آدرس نمادین یک ماشین را به جای آدرس IPآن وارد کند، تابعی که دراین مورد بکارمی آید به شکل کلی زیر است: #include <netdb.h> Struct hostent *gethostbyname(const char*name)

  7. :name رشته کاراکتری نام حوزه Name)Domain)از یک ماشین • مقداربرگشتی تابع“آدرس استراکچری است ازنوعhostent که ساختار آن به صورت زیر است: struct hostent { Char *h-name; Char **h-aliases; int h-addrtype; int h-length; Char **h-addr-list; }; #define h-addr h-addr-list[0]

  8. h-name: نام رسمی ماشین. • h-aliases: نام(های) مستعار ماشین.(این رشته با 0/ ختم میشود) • h-addrtype: خانواده آدرس برگشتی را مشخص می کند. • h-length: طول آدرس برحسب بایت. • h-addr-list: یک رشته کاراکتری که در آن آدرس IP مربوط به ماشین سرویس دهنده قرار دارد.(این رشته با 0/ ختم میشود) این تابع درصورت موفقیت آمیزبودن“یک اشاره گربه استراکچر برمی گرداند که بااین اشاره گر به مقادیرموردنظرتان دسترسی خواهید داشت ولی درصورت بروزخطامقدارNULL برخواهدگشت; برخلاف توابع قبلی درصورت بروزخطامتغیر errnoتنظیم نخواهد شدوبه جای آن متغیرسراسری herror باکد خطا تنظیم میشود.

  9. برای تحلیل نوع خطا نیز باید از تابع سیستمی herror() استفاده کنید. • انواع خطا در فراخوانی تابع gethostbyname(): کد خطا ماهیت خطا HOST-NOT-FOUND ماشین میزبانی بانام موردنظر شناخته نشد. NO_ADDRESS نام مورد نظر شناخته شدولی آدرس IPبه چنین نامی منتسب نشده. NO_DATA ماشین میزبان بانام موردنظر شناخته شدولی اطلاعاتی درموردآن یافت نشد. NO_RECOVERY درترجمه نام توسط سرویس دهنده ئ DNSخطایی رخ داده. عمل ترجمهئ نام باید ازنو تکرار شود. TRY_AGAIN

  10. :fork() یک فراخوانی سیستمی یونیکس • fork()تنها راه ایجاد یک پروسس جدید(پروس فرزند) درمحیط یونیکس است ووظیفه آن ساختن یک پروسس تکراری دقیقأ یکسان با پروسس اولیه شامل تمام مشخصه های فایل,رجیسترومنابع دیگر است. پس از اجرای fork() پروسس اولیه و پروسس همزادسازی شده راه جداگانه ای را درپیش خواهند گرفت.ازآنجایی که با دستورfork()فضای حافظه ئ پدر نیزبرای ساختن فرزند همزادسازی می شود,همه متغیرها درزمان fork()مقادیریکسان دارند اما پس ازآغاز پروسه فرزند ، تغییرات بعدی درهرکدام از آنها تأثیری برروی دیگری نخواهد گذاشت، (فقط متن دستورات برنامه بین پدروفرزند به اشتراک گذاشته میشود). تابع سیستمیfork() یک مقداربر می گرداند که برای پروسسفرزند

  11. parent main() { برابر صفروبرای پروسس پدر”pidپروسه ئ فرزند“Identifier Process )) خواهدبود.بااستفاده از pidمی توان فهمید که از بین دوپروسس کدامیک فرزند و کدامیک پدر است. به شکل روبرودقت کنید;وقتی اجرای برنامه به دستور fork()می رسد<< دستورات پس از>>آن درقالب دو پروسس مستقل کارخودرا ادامه می دهند. تمام فضای حافظه ومتغیرهای پروسه ئ پدر نیزبطورجداگانه برای پروسه ئ فرزندایجاد وبامقادیری که در پروسه ئ پدرداشته اند << مقداردهی اولیه >> می شوند وپروسه ئ پدروفرزند درمحیط سیستم عامل بطور << شبه همزمان >> و<<همروند>> اجرایخودرا ادامه می دهند. پس ازآن هرتغیری که پدریا فرزند درمتغیرهای خود ایجادکنندروی یکدیگرتاثیرنخواهند گذاشت. Fork(); Pid=…; …… } Parent child main() { main() { Fork(); Fork(); Pid=…; Pid=…; ...... } …… }

  12. با توضیحاتی که دادیم روشن است که استفادهاز()forkدر برنامه های سمت سرویس دهنده بسیارباارزش ومهم است“ چراکه وقتی برنامه شما یک اتصال معلق ومنتظررابرای سرویس دهی به حضورپذیرفت باید کد لازم برای سرویس دادن به آن راهمزادسازی کرده وبه سراغ اتصال بعدی برود وگرنه بقیه اتصالات معلق باید آنقدر انتظار بکشند تاقبلی کارش به پایان برسد وسرویس دهی به یک اتصال می تواند بین چندمیلی ثانیه تاچندین ساعت طول بکشد!! نکته:هرگاه یک پروسه ئ فرزند کارش به پایان برسد ازبینمی رود.

  13. پروسه پدررا تابع waitpid(-1,NULL,WNHANG) به حالت تعلیق خواهدبرد تازمانی که تمام پروسه های فرزندش به پایان برسند. • دلیل آنکه در برنامه های سمت سرویس دهنده اتصالات معلق به روش Polling پردازش نمی شوندوباکمک Fork() بصورت همروند به مشتری طرف مقابل خود سرویس می دهند آنست که هرگونه تأخیر دریکی از اتصالات بقیه راباتأخیرمواجه نکند بلکه به ازای هراتصال معلق،یک پروسه فرزند ایجادشود وهمه دریک سطح به صورت اشتراک زمانی سهمی اززمان CPU رادریافت کرده اجراشوند. تعداد پروسه های فرزند محدودیت دارد ولی هرپروسه فرزند که به اتمام رسید می توان بجای آن یک پروسه فرزند جدید برای اتصالی جدید ساخت.

  14. به برنامه مثال روبرو نگاه کنید: Include <stdio.h># Include <sys/types.h> # Define MAX_COUNT 200 # Void ChildProcess(void); /* ChildProcess prototype */ Void ParentProcess(void); /* parentProcess prototype */ Void main(void) { pid_t pid; pid = fork(); If (pid == 0) ChildProcess(); ParentProcess(); else }

  15. Void ChildProcess(Void) { int i; for (i=1; i<= MAX-COUNT;i++) printf(“ This line is from child, value=%d\n”, i); printf(“ *** ChildProcess is done ***\n”); } Void parentProcess(Void) { int i; for (i=1; i<= MAX-COUNT;i++) printf(“ This line is from parent, value=%d\n”, i); printf(“ *** parentProcess is done ***\n”); }

  16. parent Child Main() Main() Pid= 0 Pid= 3456 { { درمثال قبل“برنامه به گونه ای نوشته شده که پروسـۀ پدروفرزند,خودرا بشناسند چراکه اغلب اوقات پروسه ای که همزادسازی شده باید بداند که پدر است یا فرزند وبراین اساس کار متفاوتی راانجام بدهد. شکل روبرونحوه ئ اجرای برنامه ئ مثال قبل راپس از رسیدن بهfork( )را نشان می دهد: Pid=fork(); Pid=fork(); If (pid == 0) If (pid == 0) ChildProcess(); ChildProcess(); else else ParentProcess(); ParentProcess(); } } Void childProcess() Void childProcess() { ….. { ….. } } Void parentProcess() Void parentProcess() { ….. { ….. { {

  17. مثالی ازمبادلۀ اطلاعات به روش UDPمبتنی برسوکتهای دیتاگرام: Int main (void) { int sockfd; struct sockaddr_in my_addr; struct sockaddr_in their_addr; socklen_t addr_len; int numbytes; char buf[MAXBUFLEN]; if((sockfd =socket(PF_INET,SOCK_DGRAN,0)) == -1) { perror(“socket”); exit(1); }

  18. My_addr.sin_family =AF_INET; My_addr.sin_port =htons(MYPORT); My_addr.sin_addr.s_addr =INADDR_ANY; memset(&(my_addr.sin_zero),’\0’,8); if (bind(sockfd,(struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror(“bind”); exit(1); } addr_len = sizeof(struct sockaddr); if ((numbytes=revfrom(sockfd,buf,MAXBUFLEN-1,0,(struct sockaddr*)&their_addr,&addr_len))==-1) { perror(“recvfrom”); exit(1); }

  19. Printf(“got packet from %s\n” , inet_ntoa(their_addr.sin_addr)); Printf (“packet is %d bytes long\n”,numbytes); buf[numbytes] = ‘\0’; Printf (“packet contains \”%s\”\n”,buf); close(sockfd); return 0; }

  20. بلوکه شدن پروسه های تحت شبکه: • در یک عبارت ساده دستورات ورودی و خروجی، یک پروسۀ در حال اجرا را متوقف کرده وتا زمانی که عملیات دریافت داده های ورودی در خروجی کامل نشود متوقف خواهد ماند. • توابع recvto()و recv() وaccept() از این دسته اند.

  21. امکانات جاوا برای برنامه نویسی سوکت: • Java.net یک بسته از بسته های java است که در این بسته چندین نوع کلاس سوکت استریم و دیتا گرام برای برنامه نویسی شبکه تعریف شده، که جاوا دو کلاس socket و serversocket را برای برنامه نویسی با سوکت های استریم معرفی کرده است. • کلاس socket : کلاسی جهت برقراری ارتباط و مبادله داده در سمت مشتری. • کلاس server socket: کلاسی جهت تعریف ارتباط و مبادله داده در سمت سرویس دهنده.

  22. کلاسSocket : • درکلاس Socketبیش از 30متد تعریف شده که مهمترین آنها در زیر معرفی شده: Socket (String host, int port) Socket (InetAddress, int port) Synchronized Void close() InputStream getlnputStream() OutputStream getOutputStream() متدهای اول و دوم متدهای(( سازنده ئ کلاس نوع Socket)) می باشند که دارای دو تعریف مستقلند وبه دو صورت متفاوت استفاده می شوند:

  23. Socket (String host, int port):برای ایجاد کلاس سوکت ازطریق این متد,مستقیمأ آدرس نام حوزۀ یک ماشین وشماره پورت سرویس دهندۀ موردنظردرآرگومانهای آن مشخص می شود.اگر ازاین متد برای خلق یک سوکت استفاده شود،قبل ازبوجود آمدن آن ،نام حوزه بصورت خود کارتوسط DNSترجمه شده وآدرس IPآن بازخواهد گشت ودرصورت موفقیت آمیزنبودن این عمل، ادامه کارممکن نخواهد بود. مثال: قطعه کد زیرتلاش می کند یک سوکت نوع استریم ایجاد نماید: Try{ Socket sock = new Socket (“cs.wust.edu”,25); } Catch (UnknownHostException){ System.out.println (“Can’t find host.”);

  24. } Catch (IOException e) { System.out.println (“Error connecting to host.”); } • Socket (InetAddres address, int port): برای ایجاد سوکت ازطریق این متد,مستقیمأ آدرس IP یک ماشین وشماره پورت سرویس دهندۀ مورد نظردرآرگومانهای آن مشخص می شود. (آدرس IP باید به صورت رشته ای ارسال شود.) مثال زیر روش ایجاد سوکت را نشان می دهد:

  25. Try{ Socket sock = new Socket (“128.252.120”,25); } Catch (UnknownHostException) { System.out.println (“Can’t find host.”); } Catch (IOException e) { System.out.println (“Error connecting to host.”); }

  26. :Close()این متد ضمن ختم ارتباط TCP به صورت دوطرفه,سوکت را بسته ومنابع تخصیص داده شده را آزاد خواهد کرد. • getlnputStream() و getOutputStream(): برای آن است که بتوان استریمهای ورودی وخروجی ئ نسبت داده شده به سوکت رابدست آورده و بتوان از آن خواند یا در آن نوشت. به مثال زیر دقت کنید: Try{ Socket server = new Socket (“foo.bar.com”,1234); InputStream in = server.getlnputStream(); OutputStream out = server.getOutputStream(); Out.write(42); PrintStream pout = new PrintStream (out );

  27. Pout.println(“Hello!”); Byte back = in.read(); DatalnputStream din = new DatalnputStream(in); String response = din.readLine(); server.close(); } Catch (IOexception e) { }

  28. کلاس :serverSocketحال به کلاس serverSocket که درسمت سرویس دهنده ایجاد می شود وبرخی متودهای آن دقت کنید: serverSocket (int port) serverSocket (int port,int count) synchronized void close() Socket accept() متودهای اول ودوم متودهای سازنده کلاس هستند وپارامتر portدراین متود شماره پورتی است که در سمت سرویس دهنده باید به سوکت مقید شود.درمتود دوم پارامتر count زمان انتظار برای گوش دادن به پورت,جهت برقراری ارتباط است.به مثال زیر دقت کنید:

  29. Try { ServerSocket listner =new ServerSocket(1234); While (!finished) { Socket aClient = listener.accept(); // wait for connection InputStream in = aClient.getlnputStream(); OutputStream Out = aClient.getOutputStream(); Byte importantByte = in.read(); DatalnputStream din = new DatalnputStream(in); String request = din.readLine(); out.write(43); printStream pout = new printStream (out); pout.println (“Goodbye!”); aClient.Close(); } listener.Close(); } Catch (IOException e) { }

  30. دو متود در کلاس :socket • :getport این که متعلق به کلاس socket است,شماره ئ پورت انتخاب شده برای سوکت رابر می گرداند. • getHostName(): این متود نام ماشین متناظربا سوکت را برمی گرداند. این دو تابع زمانی مفیدند که درسمت سرویس دهنده,برنامه بخواهد باپذیرفتن یک ارتباط و دریافت شئ socket متناظر با آن,هویت طرف مقابل ارتباط را تشخیص بدهد.

  31. پایانفصل 7 تهیه وتنظیم: آذین قاسمی و منیرالسادات حسینی رشته IT دانشگاه پیام نور گرگان

More Related