بانک اطلاعاتی نرم افزار،سخت افزار،شبکه و برنامه نویسی

اصول برنامه نویسی شبکه (Network Socket Programming)

مقدمه

آشنایی با مفاهیم برنامه سازی شبکه، یکی از نیازهای مهندسان کامپیوتر می باشد. این افراد در مسیر کار خود با پروژه های شبکه ای روبرو خواهند شد که به احتمال زیاد نیاز به برقراری ارتباطات شبکه خواهد داشت. همچنین اگر چنین مساله ای هم اگر پیش نیاید، آشنایی با مفاهیم شبکه، دید بهتری را برای هر مهندس شبکه فراهم می سازد. از اینرو، من قصد دارم در ادامه به شرح مفاهیم و جزئیات برنامه سازی شبکه در لینوکس اشاره کنم. لازم به یاد آوری است که این مفاهیم مستقل از سیستم عامل می باشد و به راحتی می توان از آن در سیستم عاملهای مختلف استفاده کرد.

مدل سرویس دهنده / سرویس گیرنده

مدل client server


این مدل یک معماری نرم افزار توزیع شده است که در آن بار کاری و وظایف بین سرویس دهنده ها (server) و سرویس گیرنده ها (clients) تقسیم می شود. بطور معمول عملیات سرویس دهنده و گیرنده بر روی شبکه کامپیوتری که از سخت افزار مجزا تشکیل شده اند انجام می شود.

یک ماشین سرور، میزبانی است که دارای کارایی بالا  (high-performance) بوده و با اجرای یک یا چند برنامه سرویس دهنده، منابع اش را بین سرویس گیرنده ها به اشتراک می گذارد. میزبان  سرویس گیرنده منبعی را برای اشتراک ارائه نمی دهد. ولی درخواستش را جهت دریافت سرویس ارسال می کند. بنا براین، سرویس گیرنده، مقداردهی اولیه جهت ایجاد یک نشست ارتباطی را انجام می دهد و سرویس دهنده تنها منتظر (listen) دریافت درخواستها می ماند.

در ارتباطات شبکه ای، هر ماشین با آدرس IP، آدرسدهی می شود و برای آدرسدهی یک پروسس در ماشین از آدرس پورت استفاده می شود.

آدرسدهی هر پروسس با پورت

همانطور که در شکل بالا مشاهده می کنید، سرور FTP از پورت 21 استفاده می کند. با این روش می توان به راحتی چندین سرور را در یک ماشین راه اندازی کرد.

تعریف socket

از دید هسته سیستم عامل (kernel) سوکت یک نقطه انتهایی (endpoint)  ارتباط می باشد. ولی از دید برنامه کاربردی، سوکت همانند توصیفگر فایل می باشد که به آن اجازه نوشتن و خواندن به/از شبکه را می دهد.

برنامه های سرویس دهنده و سرویس گیرنده از طریق نوشتن و خواندن در توصیفگر سوکت میتوانند با هم در ارتباط باشند. تفاوت اصلی فایلهای عادی و توصیفگر سوکت در نحوه باز کردن (open) در برنامه کاربردی می باشد.

ترتیب بایتها در شبکه big-endian هست در حالی که میزبان میتواند little-endian نیز باشد. در شکل زیر تفاوت این دو به وضوح نمایش داده شده است.

LSB vs MSB

برای یکسان سازی ترتیب بایتها توابعی طراحی شده است که به قرار زیر می باشند:

- ()htons و ()htonl که ترتیب بایت میزبان را به شبکه تبدیل می کند.

- ()ntohs و ()ntohl  که ترتیب بایت را شبکه به میزبان تبدیل می کند.

در ادامه توابع مهم و پارامترهای مورد نیاز آورده شده است. توضیحات مختصر برای هر یک از پارامترها مقابل آن آورده شده است.

SOCKET: int socket(int domain, int type, int protocol);
domain := AF_INET (IPv4 protocol)
type := (SOCK_DGRAM or SOCK_STREAM )
protocol := 0 (IPPROTO_UDP or IPPROTO_TCP)
returned: socket descriptor (sockfd), -1 is an error
BIND: int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
sockfd - socket descriptor (returned from socket())
my_addr: socket address, struct sockaddr_in is used
addrlen := sizeof(struct sockaddr)

struct sockaddr_in  {
  unsigned short  sin_family;  /* address family (always AF_INET) */
  unsigned short  sin_port;    /* port num in network byte order */
  struct in_addr  sin_addr;    /* IP addr in network byte order */
  unsigned char   sin_zero[8]; /* pad to sizeof(struct sockaddr) */
};

LISTEN: int listen(int sockfd, int backlog);
backlog: how many connections we want to queue
ACCEPT: int accept(int sockfd, void *addr, int *addrlen);
addr: here the socket-address of the caller will be written
returned: a new socket descriptor (for the temporal socket)
CONNECT: int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); //used by TCP client
parameters are same as for bind()
SEND: int send(int sockfd, const void *msg, int len, int flags);
msg: message you want to send
len: length of the message
flags := 0
returned: the number of bytes actually sent
RECEIVE: int recv(int sockfd, void *buf, int len, unsigned int flags);
buf: buffer to receive the message
len: length of the buffer (“don’t give me more!”)
flags := 0
returned: the number of bytes received

SEND (DGRAM-style): int sendto(int sockfd, const void *msg, int len, int flags, const struct sockaddr *to, int tolen);
msg: message you want to send
len: length of the message
flags := 0
to: socket address of the remote process
tolen: = sizeof(struct sockaddr)
returned: the number of bytes actually sent
RECEIVE (DGRAM-style): int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
buf: buffer to receive the message
len: length of the buffer (“don’t give me more!”)
from: socket address of the process that sent the data
fromlen:= sizeof(struct sockaddr)
flags := 0
returned: the number of bytes received
CLOSE: close (socketfd);

ارتباطات سرویس دهنده / سرویس گیرنده می تواند اتصال گرا و یا بی اتصال باشد. در شکل زیر نحوه برقراری ارتباط بی اتصال را نشان می دهیم:

ارتباط connectionless

و شکل زیر نحوه ارتباط برنامه سرور و مشتری در ارتباط اتصال گرا را نمایش می دهد:

ارتباط  connection-oriented

برای بالابردن درک خواننده از مفهوم برنامه سازی شبکه، در لینک زیر مثال ساده echo  client-server  آورده شده است.

http://www.paulgriffiths.net/program/c/srcs/echoserv.tar.gz

منبع:مجید تقی لو

+ داود محمدی علی آبادی ; ۱٢:۳۸ ‎ق.ظ ; جمعه ٢۸ اسفند ۱۳۸۸
comment نظرات ()