web服務器是基於http協議,將對應的文件傳輸給客戶端的服務器。
web服務器是什麼
web服務器是基於http協議,將對應的文件傳輸給客戶端的服務器。
HTTP協議
http 協議的請求及響應方式設計
http請求信息的結構
請求信息分爲請求行、消息頭、消息體等3部分。
http響應信息結構
響應信息格式如上圖。
有了對http協議的瞭解就可以開始來看下面的代碼了。
使用方法
1、 啓動服務端 php http_server.php
2、打開瀏覽器輸入127.0.0.1:
由於 php沒有多線程,不能有效管理子進程。select、 i/o 複用epol,沒辦法高效
源碼 http_server.php
<?php
if ($argc != 2) {
$msg = sprintf("Usage: %s <port>", $argv[0]);
die($msg);
}
$host = "127.0.0.1";
$port = $argv[1];
if (($serv_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
die("socket_create() error: ". socket_strerror($serv_sock));
}
if (($ret = socket_bind($serv_sock, $host, $port)) < 0) {
die("socket_bind() error: ". socket_strerror($ret));
}
if (($ret = socket_listen($serv_sock, 4)) < 0) {
die("socket_listen() error: ". socket_strerror($ret));
}
echo "服務啓動成功 {$host}:{$port}\n";
while (1) {
if (($clnt_sock = socket_accept($serv_sock)) < 0) {
echo "socket_accept() error: ". socket_strerror($clnt_sock), "\n";
break;
} else {
$str = str_pad('', 1024);
echo "Connection Request {$str} \n";
if (!request_handler($clnt_sock)) {
}
socket_close($clnt_sock);
}
}
socket_close($serv_sock);
function request_handler($clnt_sock)
{
$req_buf = socket_read($clnt_sock, 4096);
echo "請求信息:\n";
echo $req_buf;
$req_info = explode( "\n" , $req_buf);
$req_head = $req_info[0];
if (strpos($req_head, "HTTP/") === false) {
send_error($clnt_sock);
return false;
}
$req_head_info = explode(" /" , $req_head);
if (empty($req_head_info[0])) {
send_error($clnt_sock, "http格式錯誤");
return false;
}
$method = $req_head_info[0];
$file_protocol = explode(' ', $req_head_info[1]);
$file_name = $file_protocol[0];
$file_protocol = $file_protocol[1];
$contype = content_type($file_name);
send_data($clnt_sock, $file_name, $contype);
}
function get_ext($file_name)
{
$file_info = explode('.',$file_name);
$ext = end($file_info);
return $ext;
}
function content_type($file_name)
{
$ext = get_ext($file_name);
if ($ext == "php" || $ext == "html" || $ext == "htm") {
return "text/html";
} else if ($ext == "jpg" || $ext == "jpeg") {
return "image/jpeg";
}else if ($ext == "png") {
return "image/jpeg";
} else {
return "text/html";
}
}
function send_data($clnt_sock, $file_name, $contype, $content = "")
{
$http_code = "200 OK";
if (file_exists($file_name)) {
$ext = get_ext($file_name);
if ($ext == "php") {
ob_start();
include $file_name;
$content = ob_get_contents();
ob_end_clean();
} else if($ext == "html" || $ext == "htm") {
$content = file_get_contents($file_name);
}
} else {
$content = "<html><head><title>404 not found</title></head><body style=\"text-align:center\"><span>404 not found</span></body></html>";
$http_code = 404;
}
if (empty($content)) {
$content = "<html><head><title>PHP WEB 響應</title></head><body>收到信息".date("Y-m-d H:i:s")."</body></html>";
}
$response = "HTTP/1.1 {$http_code}\r\n";
$response .= "Server: PHP Web Server \r\n";
$response .= "Content-lenth:".strlen($content)."\r\n";
$response .= "Content-type:{$contype};charset=utf-8\r\n\r\n";
$response .= $content;
echo $response,"\n";
$clnt_write = socket_write($clnt_sock, $response);
}
function send_error($clnt_sock, $content = "")
{
$file_name = "";
$html_content = "<html><head><title>PHP WEB 響應</title></head><body>出錯了{$content}</body></html>";
send_data($clnt_sock, $file_name, $html_content);
}