Серия уроков по созданию сокет клиента/сервера. Специально для пользователей Gcup.ru .
В первых трёх уроках, по многочисленным просьбам форумчан, мы рассмотрим создание сокет клиента/сервера на packal, as 3.0, php. Уроки – НЕ ДЛЯ НАЧИНАЮЩИХ, почитайте сначала книги по данным языкам программированиям, ознакомьтесь с общим функционалом.
Оглавление: • Введение, общее понятие. • Урок первый – Написание простейшего «echo-(эхо)» сокет клиента/сервера на php. • Урок второй – Оттачивание навыков, написание простейшего сокет сервера на php и клиента на pascal/as 3.0. • Урок третий - Написание простейшей игры «The movement of the squares» - «Передвижение квадратов», заключение и выводы.
Вспомогательные материалы: Справочник по сокетам на as 3.0 Справочник по сокетам на php Что нам потребуется: Любой локальный хостинг – Xampp, Denwer, Open Server, Appserv, Nginx. PSPad– программа для написания php скриптов можно и другие. Компилятор для pascal – любой. Компилятор для as 3.0 – любой, я использую adobe flash cs5. Введение:
Сокеты (англ. socket — углубление, гнездо, разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения. Следует различать клиентские и серверные сокеты.Клиентские сокеты грубо можно сравнить с оконечными аппаратами телефонной сети, а серверные — с коммутаторами. Клиентское приложение (например, браузер) использует только клиентские сокеты, а серверное (например, веб-сервер, которому браузер посылает запросы) — как клиентские, так и серверные сокеты. Интерфейс сокетов впервые появился в BSD Unix. Программный интерфейс сокетов описан в стандарте POSIX.1 и в той или иной мере поддерживается всеми современными операционными системами. Принципы сокетов: каждый процесс может создать слушающий сокет (серверный сокет) и привязать его к какому-нибудь порту операционной системы (в UNIX непривилегированные процессы не могут использовать порты меньше 1024). Слушающий процесс обычно находится в цикле ожидания, то есть просыпается при появлении нового соединения. При этом сохраняется возможность проверить наличие соединений на данный момент, установить тайм-аут для операции и т.д. Каждый сокет имеет свой адрес. ОС семейства UNIX могут поддерживать много типов адресов, но обязательными являются INET-адрес и UNIX-адрес. Если привязать сокет к UNIX-адресу, то будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём чтения/записи из него (см. Доменный сокет Unix). Сокеты типа INET доступны из сети и требуют выделения номера порта. Обычно клиент явно подсоединяется к слушателю, после чего любое чтение или запись через его файловый дескриптор будут передавать данные между ним и сервером.
Порт (TCP/IP) - В протоколах TCP и UDP (семейства TCP/IP) порт — идентифицируемый номером системный ресурс, выделяемый приложению, выполняемому на некотором сетевом хосте, для связи с приложениями, выполняемыми на других сетевых хостах (в том числе c другими приложениями на этом же хосте). По сути, порт - адресуемый участок оперативной памяти устройства, предназначенный для сетевого взаимодействия. Для каждого из протоколов TCP и UDP стандарт определяет возможность одновременного выделения на хосте до 65536 уникальных портов, идентифицирующихся номерами от 0[1] до 65535. При передаче по сети номер порта в заголовке пакета используется (вместе с IP-адресом хоста) для адресации конкретного приложения (и конкретного, принадлежащего ему, сетевого соединения). В обычной клиент-серверной модели приложение либо ожидает входящие данные (или запроса на соединение; «слушает порт»; роль сервера), либо посылает данные (или запрос на соединение) на известный порт, открытый приложением-сервером (роль клиента). По умолчанию приложению выдается порт с произвольным (например, ближайшим свободным, большим 1023) номером. При необходимости приложение может запросить конкретный (предопределённый) номер порта. Так, веб-серверы обычно открывают для ожидания соединения предопределённый порт 80 протокола TCP. Состояния порта
Состояние Описание open программа-сервер готова принимать подключения
listen filtred файрвол или иная причина не позволяет nmap'у определить открыт или зарыт порт closed
Номера портов - Порты TCP не пересекаются с портами UDP. То есть, порт 1234 протокола TCP не будет мешать обмену по UDP через порт 1234. Ряд номеров портов стандартизован (см. Список портов TCP и UDP). Список поддерживается некоммерческой организацией IANA.В большинстве UNIX-подобных операционных систем прослушивание портов с номерами 0—1023 (почти все из которых зарегистрированы) требует особых привилегий. Каждый из остальных портов может быть захвачен первым запросившим его процессом. Однако, зарегистрировано номеров намного больше, чем 1024.
Урок первый: Включив локальный сервер, создадим в локальной папке два файла с расширением php – server.php и client.php. Ниже приведён код их содержания. server.php
Код, в принципе, прокомментирован, путём вывода на экран вспомогательного сообщения, если какие-то части не понятны – обращайтесь.Ещё раз повторяю урок НЕ ДЛЯ НОВИЧКОВ, поэтому код прокомментирован НЕСИЛЬНО. Давайте же протестируем наш сокет клиент/сервер – последовательно зайдите на страницы server.php и client.php. В итоге, если всё правильно сделали, у вас получится так: Данный сервер неудобен тем, что он может прослушивать только одного клиента, в следующих уроках мы научим сервер слушать сразу несколько клиентов.
Урок второй: Включив локальный сервер, создадим в локальной папке три файла – server.php и client.fla и client.pas. Ниже приведён код их содержания.
Server.php
Code
<?php header('Content-Type: text/plain;'); set_time_limit(0); ob_implicit_flush(); echo "-= Server =-\n\n";
while(!$abort){ $num_changed = socket_select($read, $NULL, $NULL, 0, 10); /* Изменилось что-нибудь? */ if ($num_changed){ /* Изменился ли главный сокет (новое подключение) */ if(in_array($creat, $read)){ if(count($sockets_clients) < $max_clients){ $sockets_clients[]= socket_accept($creat); echo " Accept socket (" . count($sockets_clients) . " of $max_clients clients)\n"; socket_write($sockets_clients[count($sockets_clients)-1], "Hello, Client!", 15); echo " Say to ".count($sockets_clients)." client: Hello, Client!\n"; } } /* Цикл по всем клиентам с проверкой изменений в каждом из них */ foreach($sockets_clients as $key => $client){
/* Новые данные в клиентском сокете? Прочитать и ответить */ if(in_array($client, $read)){ $input = socket_read($client, 1024);
$read = $sockets_clients; $read[] = $creat; } // END WHILE ?>
Client.pas
Code
uses Sockets; var sock: integer; b: boolean; s,m: string; begin cls; sock:=CreateClientSocket; b:=Connect(sock,'127.0.0.1',1024); if not b then begin writeln('Ñîåäèíåíèå çàâåðøèëîñü íåóäà÷íî'); Exit; end; repeat sleep(100); ReceiveString(sock,m); writeln(m); read(s); SendString(sock,s); until s='bye'; CloseSocket(sock); end.
Client.fla Создадим слой с названием action и напишем в нём код.
Code
/* connect to socket */ var socket = new Socket("localhost", 1024); socket.connect; socket.flush;
/* state of connect to socket */ socket.addEventListener(Event.CONNECT,socketConnected); function socketConnected(e:Event):void{ trace("client - socket connected", socket.connected); }
/* read the string from the socket*/ socket.addEventListener(ProgressEvent.SOCKET_DATA,socketData); function socketData(e:ProgressEvent):void{ var read_socket=socket.readUTFBytes(socket.bytesAvailable); trace(read_socket); }
socket.writeUTFBytes('bye');
socket.close;
Ну вот на сегодня и всё. Код, в принципе, прокомментирован, путём вывода на экран вспомогательного сообщения, так же имена переменных помогут ориентироваться, если какие-то части не понятны – обращайтесь. Ещё раз повторяю урок НЕ ДЛЯ НОВИЧКОВ, поэтому код прокомментирован НЕСИЛЬНО. Давайте же протестируем наш сокет клиент/сервер – зайдите на страницу server.php и откройте client.pas/fla. Должно получиться что-то вроде этого. Данный сервер неудобен тем, что он отправляет данные обратно, а не всем клиентам, в следующих уроках мы научим сервер отправлять сообщения сразу нескольким клиентам.
Третий урок добавлен внизу страницы.
Спасибо за внимание! (Троллей и флудерщеков сразу попрошу обойти тему мимо! И писать что-то вроде «Да кому нужен сервер на php» не стоит, раз урок написан – значит кому-то нужен!)
Сообщение отредактировал anton-gar - Понедельник, 12 Марта 2012, 14:32
Ну не знаю... погуглил, нашел идентичный код, просто помню что где-то такое уже видел... Вот в чем смысл?! Накопировал инфы и оформил.. написал бы тогда хоть комменты подробные на каждую строчку, чтобы больше пользы было. Или же ТС просто сам не знает, что там и зачем?! Остальные уроки тоже будут копипастом?
Мне вообще всё равно, но просто смысла в этом не вижу. С таким же успехом можно было дать ссылки на википедию и на код.
Ну не знаю... погуглил, нашел идентичный код, просто помню что где-то такое уже видел... Вот в чем смысл?! Накопировал инфы и оформил.. написал бы тогда хоть комменты подробные на каждую строчку, чтобы больше пользы было. Или же ТС просто сам не знает, что там и зачем?!
Согласен, по этому я разбирал, вот и дал для разогрева!
Не без этого , честно - просто в Паскале чувствую пока себя лучше, чем в as3.0, вот и тестел с паскаля, а когда всё наладил, написал на флеше клиент.
Добавлено (25.02.2012, 00:03) --------------------------------------------- LunarPixel, а уроков/статей по сокет связи as3.0 и php я вообще не нашёл, были только темы, в которых в основном через xml.
Материал взяты из Википедии — свободной энциклопедии
И смысл, у кого-то нету мозгов в вики зайти? А почему серве только под виндой или маком, кто сейчас сервера на винде-то держит?
anton-gar, что-то не вижу смысла в таких уроках. Написаны сложно и нудно. Человек, который осилит это прочитать- с тем же успехом может открыть гугл и найти всю инфу. Собственно, что за извращение. Зачем вообще делать и клиент, и сервер на php? Зачем писать бесполезный урок? Я даже не вижу, где это может применяться.
Зачем вообще делать и клиент, и сервер на php? Зачем писать бесполезный урок? Я даже не вижу, где это может применяться.
Quote (anton-gar)
Введение, общее понятие. • Урок первый – Написание простейшего «echo-(эхо)» сокет клиента/сервера на php.
Quote (anton-gar)
И писать что-то вроде «Да кому нужен сервер на php» не стоит, раз урок написан – значит кому-то нужен!)
А так - что бы проверить работу сервера. --------------------------------------------- Да, этот урок был не самый, но для общего понятия подойдёт. Думаю, последующие будут гораздо интересней и нужней!
Добавлено (09.03.2012, 11:58) --------------------------------------------- Добавлен второй урок. --------------------------------------------- Добавлено видео 3 урока.
Сообщение отредактировал anton-gar - Пятница, 09 Марта 2012, 15:30
while(!$abort){ $num_changed = socket_select($read, $NULL, $NULL, 0, 10); /* Изменилось что-нибудь? */ if ($num_changed){ /* Изменился ли главный сокет (новое подключение) */ if(in_array($creat, $read)){ if(count($sockets_clients) < $max_clients){ $sockets_clients[]= socket_accept($creat); echo " Accept socket (" . count($sockets_clients) . " of $max_clients clients)\n"; // socket_write($sockets_clients[count($sockets_clients)-1], "Hello, Client!", 15); echo " Say to ".count($sockets_clients)." client: Hello, Client!\n"; } } /* Цикл по всем клиентам с проверкой изменений в каждом из них */ foreach($sockets_clients as $key => $client){
/* Новые данные в клиентском сокете? Прочитать и ответить */ if(in_array($client, $read)){ $input = socket_read($client, 1024);
$read = $sockets_clients; $read[] = $creat; } // END WHILE ?>
Client.fla На временной шкале создадим два слоя - первый с названием action в нём напишем код, второй – sqrs в нем будут находиться квадраты. В слой sqrs добавьте два квадрата, преобразуйте их в символы и в свойствах назначьте имена экземплярам: первый - sqr и второй - sqr_i, задайте им размер и положение, я делал так – размер 50*50, положение – (25;25). Далее добавьте код в слой action.
Code
/* connect to socket */ var socket = new Socket("localhost", 1024); socket.connect; socket.flush;
/* state of connect to socket */ socket.addEventListener(Event.CONNECT,socketConnected); function socketConnected(e:Event):void{ trace("client - socket connected", socket.connected); }
/* read the string from the socket*/ socket.addEventListener(ProgressEvent.SOCKET_DATA,socketData); function socketData(e:ProgressEvent):void{ var x1=''; var y1=''; var read_socket=socket.readUTFBytes(socket.bytesAvailable); if (read_socket.indexOf('x')==0){ for (var i=1; i<read_socket.length; i++){ x1=x1+read_socket.charAt(i); } sqr.x=Number(x1); } if (read_socket.indexOf('y')==0){ for (i=1; i<read_socket.length; i++){ y1=y1+read_socket.charAt(i); } sqr.y=Number(y1); } trace(read_socket); }
/*Move to sqr*/ var speed:Number = 5; stage.addEventListener(KeyboardEvent.KEY_DOWN, downn);
/*sqr.addEventListener(Event.ENTER_FRAME, sqr_move); function sqr_move(e:Event): void{ sqr.y=Number(socket.readUTFBytes(socket.bytesAvailable)); }*/
/*close to socket*/ socket.close;
Ну вот на сегодня и всё. Код, в принципе, прокомментирован, путём вывода на экран вспомогательного сообщения, так же имена переменных помогут ориентироваться, если какие-то части не понятны – обращайтесь. Ещё раз повторяю урок НЕ ДЛЯ НОВИЧКОВ, поэтому код прокомментирован НЕСИЛЬНО. Давайте же протестируем наш сокет клиент/сервер – зайдите на страницу server.php и откройте client.swf два раза.
В результате получится что-то вроде этого. Исходник. Данная «игра» далеко не безупречна, но принцип, думаю, ясен, дальше доделывайте сами.
На этом всё, данная серия уроков окончена, хотя возможно дам тестовый урок. Спасибо за внимание! Удачи в изучении!
Сообщение отредактировал anton-gar - Понедельник, 12 Марта 2012, 14:41