socket與curl
來源:互聯網
上載者:User
Socket是什麼。能幹什麼。長什麼樣。大致的原理是什麼。我想還是給出執行個體來最好理解。
在這裡,我還是用java來實現一個socket的服務端與用戶端(你也可以用任何其他支援socket操作的語言來實現),然後用php來做為用戶端請求該通訊端。如下圖所示,在伺服器端使用socket開了一個服務,連接埠是8001,那麼我就可以建立多個用戶端來進行串連。在用戶端,我向該socket發送一條訊息,伺服器端在收到了我的訊息後,會根據情況進行一定的處理,返回給用戶端,同時在伺服器端列印所有收到的訊息。
從圖1,我們看到伺服器端和用戶端都採用java實現,在圖一的中間第二張圖那裡,我們看到,一旦我開啟了伺服器端,那麼我這個服務就會被註冊到windows的網路服務中,連接埠為8001,為了讓你確信,我們可以用netstat命令來列印本機各連接埠的網路連接情況,在列印列表裡,可以看到此服務已經被註冊了。一旦有用戶端串連此socket,作業系統就會為用戶端自動分配一個隨機連接埠來和伺服器端8001連接埠進行通訊。
既然此服務已經被註冊到作業系統中,那麼其實此服務和你的QQ,FTP等實際上是一個層級的了,你可以用它來做太多太多的事情。為了驗證一下,我們呢可以使用telnet來串連它。
由於socket是開放的,透明的,一旦運行,也就是說任何可以操作socket的語言都可以訪問這個開放的服務,圖一是使用java來訪問socket,我們也可以使用php,甚至js(HTML5的新特性http://dev.w3.org/html5/websockets/)來訪問此服務。
例七:Php端代碼如下:
<?php
$sock = fsockopen("192.168.0.2", 8001, $errno, $errstr,1);
if (!$sock)
{
echo "$errstr ($errno)<br/>\n";
}else{
//socket_set_blocking($sock,false);
fwrite($sock, "senddata....\r\n");//注意:資料末尾需要加上"\r\n"來提交此請求資料,否則可能將無法擷取服務端的回應,即使重新整理緩衝也無效,這樣就只有等到此串連關閉時才能擷取到回應。
fwrite($sock, "end\r\n"); //使用end命令終止此用戶端串連
while (!feof($sock)) {
echo fread($sock, 128);
flush();
ob_flush();
sleep(1);
}
fclose($sock);
}
運行後,結果如下:
想要知道更多細節,可以使用IRIS抓包軟體。
好了,看了這麼多示範,我想你對socket應該能有一個比較直觀的認識了吧。現在我來總結一下socket是個神馬東東。翻開百度百科,可以看到如下定義:“作為4BDSUNIX的進程通訊機制,取後一種意思。通常也稱作"通訊端",用於描述IP地址和連接埠,是一個通訊鏈的控制代碼。”所謂socket通常也稱作"通訊端",應用程式通常通過"通訊端"向網路發出請求或者應答網路請求。說白了就是一種通訊機制。它類似於銀行,電信啊這些部分的電話客服部門。你打電話的時候,那邊會分配置一個人回答你的問題,客服部門就相當於socket的伺服器端了,你這邊呢就相當於用戶端了,在和你通話結束前,如果有人在想找和你通話的那個說話,是不可能的,因為你在和他通訊,當然客服部門的電話交換器也不會重複分配。
我們可以來看一個socket函數的原型定義:
SOCKET socket( int af, int type, int protocol );
第一個參數指定應用程式使用的通訊協定的協議族,對於TCP/IP協議族,該參數置AF_INET,對於unix,可建立本地socket;
第二個參數指定要建立的通訊端類型,流通訊端類型為SOCK_STREAM、資料通訊端類型為SOCK_DGRAM;
第三個參數指定應用程式所使用的通訊協定。
要想深入到socket的內部實現機制是很困難的,作為一名非底層程式員,我們只要能明白socket是一套作業系統封裝好的函數,會建立能調用就OK了。在PHP裡,要想建立一個socket是很輕鬆地事情。
例八:代碼如下:
<?php
$host = "192.168.0.2";
$port = 12345;
set_time_limit(0);//最好在CLI模式下運行
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could notcreate socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bindto socket\n");
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socketlistener\n");
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incomingconnection\n");
// read client input
$input = socket_read($spawn, 1024) or die("Could not readinput\n");
// clean up input string
$input = trim($input);
// reverse client input and send back
$output = strrev($input) . "\n";
socket_write($spawn, $output, strlen ($output)) or die("Could notwrite output\n");
// close sockets
socket_close($spawn);
socket_close($socket);
這 段代碼的注釋已經很詳細了,如果你還想知道更多內情,可以訪問http://www.devshed.com/c/a/PHP/Socket-Programming-With-PHP/,這個網站對socket的建立和使用進行來了很詳細的講解。由於PHP不支援多線程,只適合做用戶端,而不適合做服務端,效能相對不高。所以一般服務端都是用C/JAVA等語言來實現,因此關於PHP建立socket服務端我就不做過多介紹了。(順便提下:看到有人問PHP實現多線程的問題,有人一直堅稱PHP可以實現多線程,甚至稱自己已經寫出一個多線程或者類比出一個多線程了。其實很多人只是把多進程或者大量操作看做多線程,或者藉助一些PHP的夥伴,linux作業系統或者web伺服器來近似實現的。我想說的是,線程這玩意,不是某些人想得那麼簡單的。線程調度,線程間訊息傳遞,休眠和喚醒,線程池,同步,鎖,優先順序等概念不是玩的,如果有人聲稱自己用php實現了多線程,那希望你能給我個完整的線程操作。或許,我會認為自己是孤陋寡聞。)
另外,PHP的記憶體管理是非常非常糟糕的。由於它代替我們做了99%的記憶體管理,所以我們根本無法實現對記憶體的據需管理,而這在應用級服務上是致命的,所以PHP不能做應用及伺服器端開發。即使它聲稱有防止記憶體泄露的機制,但實際上並非如此,也不要以為PHP就不存在野指標這類的問題。所以糾結於PHP多線程的PHP程式員都是蛋疼郎,除非你精通C,準備改造PHP源碼。這個工作已經有人做了,不得不佩服這些TOP1%的PHP高手。剩下的99%就洗洗睡吧。以後,別在我面前提PHP的多線程及神馬伺服器開發。
要在用戶端操作socket,除了可以使用fsockopen函數外,還可以使用socket_create,stream_socket_client函數來實現。具體可以看手冊。如果是php5的話,我建議使用stream_socket來實現socket操作。