Абстрактен клиент TCP - Банка от резюмета, есета, доклади, курсови работи и дипломни работи
Сървъри и клиенти
Има няколко вида сокети: потокови сокети и дейтаграмни сокети. Дейтаграмните гнезда не гарантират безопасността на предаваните данни. Сокетите от този тип са подходящи само за обмен на потребителски съобщения, така че няма да се фокусираме върху тях. Поточните гнезда осигуряват надеждна двупосочна комуникация.
Като цяло процесът на свързване може да бъде разделен на няколко етапа. На първо място, трябва да получите идентификатора на създавания сокет (в противен случай - името), независимо дали е клиент или сървър. След това и клиентът, и сървърът трябва да създадат сокет с посоченото име. След това сървърът преминава в режим на изчакване за входящи връзки и клиентът се опитва да се свърже със сървъра. В случай на успешно завършване на тези етапи, имаме готова връзка: дескриптор за четене / запис за сървъра и подобен за клиента. Сега можете да започнете да обменяте данни. В процеса на анализиране на принципите на междупроцесна комуникация вече се сблъскахме с проблема с отворените манипулатори. И така, същото е и със сокетите: не забравяйте да затворите дескриптори. Вероятно обаче все пак ще се сблъскаме с този проблем, защото ни очакват цял куп клопки, които ще трябва да бъдат подредени при работа със сокети.
Нека започнем с прост пример - получаване на документ чрез HTTP протокола. Има специален интерфейс, който улеснява работата със сокети от Perl - IO::Socket. Ние обаче няма да използваме IO::Socket, тъй като искаме да имаме максимален контрол върху връзката. Реално обаче използването на IO::Socket прави работата със сокети много по-лесна и също така значително намалява риска от грешка. Когато решавате реални проблеми, препоръчвам да използвате IO::Socket.
Затова нарекох програмата "gethttp.pl". Насще ви е необходим модулът Socket, който изпълнява всички необходими специфични за платформата функции. На първо място, това се отнася до функцията за идентификация на гнездото. Но всичко е наред.
die "Използване: gethttp.pl [хост] [документ]n";
my $sock_name = GetSockName($ARGV[0],80)
or die "Не може да се преобразува $ARGV[0] в интернет адрес: $!n";
или умрете "Не може да се свърже с $ARGV[0]: $!n";
print CONN "GET $ARGV[1] HTTP/1.0n";
print CONN "Хост: $ARGV[0]nn";
След свързване на модула Socket проверяваме дали са подадени достатъчно аргументи на входа на програмата. Според описанието стартирането на програмата трябва да бъде аргументирано с две стойности: името на хоста и виртуалния път на документа, който ще бъде получен. Така че, ако масивът от входни аргументи не съдържа необходимите два аргумента, тогава програмата приключва.
Изпълнението на функцията за идентификация на гнездото според мен е много удобно, тъй като крие цялата неразбираемост. Освен това, както казах, определянето на името на сокета е задължителен процес както за сървъра, така и за клиента. Следователно можем лесно да използваме функцията GetSockName() в следващите ни програми.
След като идентифицираме сокета, ние създаваме сокета с помощта на вградената функция socket(). Като аргументи тази функция приема манипулатор на връзка (забележка: обикновен манипулатор на файл), константа, указваща обхвата на сокета (PF_INET или PF_UNIX), константа, указваща типа на сокета (дейтаграма или поток) и идентификатор на протокол. Идентификаторът на протокола, съответстващ на набора в системата, се определя от числовата стойност c с помощта на функцията getprotobyname().
След като сокетът е създаден, ние се опитваме да се свържем с отдалечения сървър. Това се прави с помощта на функцията connect(), катокойто приема дескриптор на сокет и идентификатор като аргументи. Ако опитът за свързване е неуспешен, програмата се прекратява с грешка. Следват инструкциите за печат, които, следвайки правилата на HTTP протокола, обявяват необходимостта от издаване на посочения документ. Ние съхраняваме получените от сървъра данни в масива @body. Затваряме връзката и показваме съдържанието на масива @body. Ето нашия документ.
Сега нека анализираме функцията GetSockName().
връща undef освен ако не е дефинирано ($nm);
връща undef, освен ако не е дефинирано ($pt);
върне undef, освен ако $nm = gethostbyname($nm);
Сега нека опитаме това, което имаме. Стартираме програмата и Хахаха. Какво, закъсал отново? И така, къде е нашата грешка? Точно така, забравихме да деактивираме буферирането. Данните изглежда са изпратени, но има твърде малко от тях, за да запълнят буфера. Следователно всъщност нашите изпратени данни са заседнали на сокета. А сървърът чака и чака клиентът да заяви желанието си. Нека да поправим нещата и да добавим следния код между редовете:
или умрете "Не може да се свърже с $ARGV[0]: $!n";
изберете (CONN); $=1; изберете (STDOUT);
print CONN "GET $ARGV[1] HTTP/1.0n";
Сега всичко трябва да работи.
Нашата програма, разбира се, не е супер-дупер, но все пак ще се побере за нещо. Например, ако отделите заглавките на отговора от тялото на самия отговор, можете да изтегляте файлове през HTTP. Нека го направим.
Както знаем, отговорът на сървъра се състои от заглавка и тяло. Освен това заглавката на отговора е отделена от тялото с два нови реда. Тук намираме тези два нови реда:
print CONN "GET $ARGV[1] HTTP/1.0n";
print CONN "Хост: $ARGV[0]nn";
Сега можем да изпълним командата:
[root@avalon скриптове]# ./gethttp.pl вихър /index.cgi > index.html
за да получите HTML кода на индексната страница на нашия сайт.
Е, това е, като за начало. Вече имате достатъчно умения, за да работите с протоколи от високо ниво. Така че опитайте да работите с FTP или SMTP.