基於 TCP Socket 的文件傳輸示例,展示服務端監聽接收、客戶端發送的完整流程,適合理解網絡編程基礎或特殊場景(如內網設備互傳)。
<?php
set_time_limit(0); // 長運行腳本取消超時
error_reporting(E_ALL);
$host = '192.168.3.57';
$port = 1337;
$save_path = 'e:/web/'; // Windows 路徑,Linux 改為 /home/upload/
// 創建 Socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) die("socket_create 失敗: " . socket_strerror(socket_last_error()));
// 綁定地址
if (!socket_bind($socket, $host, $port)) die("socket_bind 失敗: " . socket_strerror(socket_last_error()));
// 監聽
if (!socket_listen($socket, 5)) die("socket_listen 失敗: " . socket_strerror(socket_last_error()));
echo "服務端啟動,監聽 $host:$port ...\n";
while (true) {
// 接受連接
$client = socket_accept($socket);
if (!$client) continue;
// 發送歡迎信息
$msg = "telnet succeed!\r\n";
socket_write($client, $msg, strlen($msg));
$fp = null;
$buffer = '';
// 接收數據循環
while ($bytes = @socket_recv($client, $buffer, 1024, 0)) {
if ($bytes === false) break;
// 解析文件名(簡易協議:首包含 filename:xxx)
if ($fp === null && false !== strpos($buffer, 'filename:')) {
$filename = trim(substr($buffer, 9)); // 9 = strlen('filename:')
$filename = basename($filename); // 安全過濾
$filepath = $save_path . $filename;
$fp = fopen($filepath, 'wb');
if (!$fp) {
echo "無法創建文件: $filepath\n";
break;
}
echo "開始接收文件: $filename\n";
continue; // 首包不寫入文件內容
}
if ($fp) {
fwrite($fp, $buffer);
}
}
if ($fp) {
fclose($fp);
echo "文件接收完成\n";
}
socket_close($client);
}
socket_close($socket);
?>
<?php
$host = '192.168.3.57';
$port = 1337;
$local_file = '../../iphone3G.bmp';
$remote_name = 'socket_file.bmp';
$fp = fsockopen($host, $port, $errno, $errstr, 10);
if (!$fp) {
die("連接失敗: $errstr ($errno)\n");
}
echo "連接成功\n";
// 發送文件名協議
$header = "filename:$remote_name";
fwrite($fp, $header);
// 發送文件內容
$content = file_get_contents($local_file);
if ($content === false) {
die("讀取本地文件失敗\n");
}
fwrite($fp, $content);
// 發送結束標記(可選)
fwrite($fp, 'over');
echo "上傳完成\n";
fclose($fp);
?>
簡易文本協議:
filename:xxx.extover 結束標記)
| 點 | 說明 |
|---|---|
| socket_create | AF_INET=IPv4, SOCK_STREAM=TCP, SOL_TCP=協議 |
| socket_bind | 綁定 IP:Port,0.0.0.0 表示所有網卡 |
| socket_listen | backlog=5 等待隊列長度 |
| socket_accept | 阻塞等待客戶端連接,返回新 Socket 資源 |
| socket_recv | 接收數據,flags=0 正常,MSG_WAITALL 等待滿緩衝區 |
| socket_write | 發送數據,返回發送字節數 |
| fsockopen | 客戶端高級封裝,返回文件指針,可用 fread/fwrite |
socket_set_nonblock() + socket_select() 處理高併發
3. SSL/TLS 加密:stream_socket_enable_crypto() 或 OpenSSL 擴展
4. 進程管理:pcntl_fork() 多進程、或 Swoole/Workerman 框架
5. 文件完整性:傳輸後驗證 MD5/SHA256
Socket 編程是網絡通信基石,理解其同步阻塞模型是進階高性能網絡編程的前提。