PHP Conference Japan 2024

socket_write

(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)

socket_write寫入 socket

說明

socket_write(Socket $socket, string $data, ?int $length = null): int|false

函式 socket_write() 將指定的 data 寫入 socket

參數

socket

data

要寫入的緩衝區。

length

選用參數 length 可以指定寫入 socket 的位元組數。如果此長度大於緩衝區長度,則會自動截斷為緩衝區的長度。

返回值

成功寫入 socket 的位元組數,失敗則返回 false。錯誤碼可以使用 socket_last_error() 取得。此程式碼可以傳遞給 socket_strerror() 以取得錯誤的文字說明。

注意事項:

socket_write() 返回零是完全有效的,這表示沒有寫入任何位元組。請務必使用 === 運算子來檢查是否有 false 的錯誤。

更新日誌

版本 說明
8.0.0 socket 現在是 Socket 的實例;以前,它是 resource
8.0.0 length 現在可以為 null。

備註

注意事項:

socket_write() 不一定會寫入指定緩衝區中的所有位元組。根據網路緩衝區等情況,即使您的緩衝區較大,也可能只寫入一定量的數據,甚至只有一個位元組,這是有效的。您必須注意,以免無意中忘記傳輸其餘數據。

參見

新增註解

使用者貢獻的註解 5 則註解

8
revelable at hotmail dot com
13 年前
這裡我們使用相同的函式來寫入 socket,但效能有所提升。

如果訊息不大,它們將會透過單次的 socket_write() 呼叫完整寫入。而且在第一個迴圈中不需要呼叫 substr() 函式。

<?php
$st
="Message to sent";
$length = strlen($st);

while (
true) {

$sent = socket_write($socket, $st, $length);

if (
$sent === false) {

break;
}

// 檢查是否已傳送完整訊息
if ($sent < $length) {

// 如果未傳送完整訊息。
// 將尚未傳送的訊息部分作為訊息
$st = substr($st, $sent);

// 取得未傳送部分的長度
$length -= $sent;

} else {

break;
}

}
?>
1
匿名
3 年前
傳送數 MB 或更多資料會導致傳輸不完整,請改用迴圈和區塊方式傳送資料,socket_write 即使只傳輸了部分資料也會回報寫入完成,這可能是因為某些地方的緩衝區溢位。

$strlen=strlen($msg);
$totaltransferred=0;

$blocksize=10000;
for ($a=0;$a<$strlen;$a+=$blocksize){
$part=substr($msg,$a,$blocksize);
$transferred=socket_write($socket,$part,strlen($part));
$totaltransferred+=$transferred;
}

if ($totaltransferred<$strlen){
echo "incomplete transfer"; // 傳輸不完整
}
2
gtk at linux dot online dot no
22 年前
來自 http://www.manualy.sk/sock-faq/unix-socket-faq-2.html
read() 等同於 flags 參數為 0 的 recv()。flags 參數的其他值會改變 recv() 的行為。同樣地,write() 等同於 flags == 0 的 send()。
1
php at deguest dot asia
9 年前
我經常在 PHP 文件中看到使用者沒有檢查 PHP 函式的回傳值,在 socket_write 的情況下,我沒有在這裡的評論中看到任何人費心去讀取伺服器在 socket 上的回覆。
然後有一位使用者認為在 SMTP 連線上的 socket_write 之後使用 usleep 會是一個好主意。
實際上,如果您檢查伺服器的回覆,不僅可以在您再次寫入 socket 之前給伺服器時間回覆,這也是一個檢查伺服器回覆內容的好機會。
例如,對於 SMTP 連線
在此範例中,MAIL_SERVER、MAIL_PORT 和 DEBUG 是我定義的常數。
<?php
function sendmail( $param )
{
$from = &$param[ 'from' ];
$to = &$param[ 'to' ];
$message = &$param[ 'data' ];

$isError = function( $string )
{
if(
preg_match( '/^((\d)(\d{2}))/', $string, $matches ) )
{
if(
$matches[ 2 ] == 4 || $matches[ 2 ] == 5 ) return( $matches[ 1 ] );
}
else
{
return(
false );
}
};

try
{
$socket = null;
if( (
$socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP ) ) == false )
{
throw new
Exception( sprintf( "Unable to create a socket: %s", socket_strerror( socket_last_error() ) ) );
}
if( !
socket_connect( $socket, MAIL_SERVER, MAIL_PORT ) )
{
throw new
Exception( sprintf( "Unable to connect to server %s: %s", MAIL_SERVER, socket_strerror( socket_last_error() ) ) );
}
$read = socket_read( $socket, 1024 );
if(
$read == false )
{
throw new
Exception( sprintf( "Unable to read from socket: %s", socket_strerror( socket_last_error() ) ) );
}

if(
socket_write( $socket, sprintf( "HELO %s\r\n", gethostname() ) ) === false )
{
throw new
Exception( sprintf( "Unable to write to socket: %s", socket_strerror( socket_last_error() ) ) );
}
$read = socket_read( $socket, 1024 );
if(
$read == false )
{
throw new
Exception( sprintf( "Unable to read from socket: %s", socket_strerror( socket_last_error() ) ) );
}
else
{
if( (
$errCode = $isError( $read ) ) ) throw new Exception( "Server responded with an error code $errCode" );
}

if(
socket_write( $socket, sprintf( "MAIL FROM: %s\r\n", $from ) ) === false )
{
throw new
Exception( sprintf( "Unable to write to socket: %s", socket_strerror( socket_last_error() ) ) );
}
$read = socket_read( $socket, 1024 );
if(
$read == false )
{
throw new
Exception( sprintf( "Unable to read from socket: %s", socket_strerror( socket_last_error() ) ) );
}
else
{
if( (
$errCode = $isError( $read ) ) ) throw new Exception( "Server responded with an error code $errCode" );
}
/* And some more code, but not enough place in comment */
return( $totalWriten );
}
catch(
Exception $e )
{
$ERROR = sprintf( "Error sending mail message at line %d. ", $e->getLine() ) . $e->getMessage();
return(
false );
}
}
-3
webmaster at you-are-infected dot com
18 年前
如果您以類似 telnet 或其他類似協定的方式連線到伺服器,您可能會在將資料傳送到伺服器時遇到問題。我發現某些伺服器在…方面有所不同

<?php

socket_write
($my_socket, $line, strlen ($line));
socket_write ($my_socket, "\r\n", strlen ("\r\n"));

?>
至少這個方法有效,而且
<?php
socket_write
($my_socket, $line."\r\n", strlen ($line."\r\n"));
?>
這會導致伺服器停止發送任何資料。

希望這可以節省很多時間。我花了大約兩天才發現這就是問題所在 ;)
To Top