PHP Conference Japan 2024

socket_write

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

socket_write写入套接字

描述

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

函数 socket_write() 从给定的 data 中写入 socket

参数

socket

data

要写入的缓冲区。

length

可选参数 length 可以指定写入套接字的字节的备用长度。如果此长度大于缓冲区长度,则会静默截断为缓冲区长度。

返回值

返回成功写入套接字的字节数,或在失败时返回 false。可以使用 socket_last_error() 获取错误代码。此代码可以传递给 socket_strerror() 以获取错误的文本解释。

注意:

socket_write() 返回零是完全有效的,这意味着没有写入任何字节。在发生错误时,请务必使用 === 运算符检查 false

变更日志

版本 描述
8.0.0 socket 现在是 Socket 实例;以前,它是一个 resource
8.0.0 length 现在可以为 null。

备注

注意:

socket_write() 不一定会写入给定缓冲区中的所有字节。根据网络缓冲区等,即使您的缓冲区更大,也可能只写入一定数量的数据(甚至一个字节),这是有效的。您必须注意,不要无意中忘记传输数据的其余部分。

参见

添加注释

用户贡献的注释 5 条注释

revelable at hotmail dot com
13 年前
这里我们有相同的函数来写入套接字,但性能有所提高。

如果消息不大,它们将通过单个 socket_write() 调用完全写入。并且不需要为第一个循环调用 substr() 函数。

<?php
$st
="要发送的消息";
$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;
}

}
?>
anonymous
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 "传输不完整";
}
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()。
php at deguest dot asia
9 年前
我经常在 php 文档中看到用户没有检查 php 函数的返回值,在 socket_write 的情况下,我在这里的评论中没有看到任何人关心读取服务器回复。
然后一个用户认为在 smtp 连接上 socket_write 后使用 usleep 是一个好主意。
实际上,如果您检查服务器回复,它不仅会给服务器时间在您再次写入套接字之前回复,而且也是检查服务器回复给您的内容的好机会。
例如,对于 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( "无法创建套接字: %s", socket_strerror( socket_last_error() ) ) );
}
if( !
socket_connect( $socket, MAIL_SERVER, MAIL_PORT ) )
{
throw new
Exception( sprintf( "无法连接到服务器 %s: %s", MAIL_SERVER, socket_strerror( socket_last_error() ) ) );
}
$read = socket_read( $socket, 1024 );
if(
$read == false )
{
throw new
Exception( sprintf( "无法从套接字读取: %s", socket_strerror( socket_last_error() ) ) );
}

if(
socket_write( $socket, sprintf( "HELO %s\r\n", gethostname() ) ) === false )
{
throw new
Exception( sprintf( "无法写入套接字: %s", socket_strerror( socket_last_error() ) ) );
}
$read = socket_read( $socket, 1024 );
if(
$read == false )
{
throw new
Exception( sprintf( "无法从套接字读取: %s", socket_strerror( socket_last_error() ) ) );
}
else
{
if( (
$errCode = $isError( $read ) ) ) throw new Exception( "服务器返回错误代码 $errCode" );
}

if(
socket_write( $socket, sprintf( "MAIL FROM: %s\r\n", $from ) ) === false )
{
throw new
Exception( sprintf( "无法写入套接字: %s", socket_strerror( socket_last_error() ) ) );
}
$read = socket_read( $socket, 1024 );
if(
$read == false )
{
throw new
Exception( sprintf( "无法从套接字读取: %s", socket_strerror( socket_last_error() ) ) );
}
else
{
if( (
$errCode = $isError( $read ) ) ) throw new Exception( "服务器返回错误代码 $errCode" );
}
/* 还有更多代码,但注释中空间不足 */
return( $totalWriten );
}
catch(
Exception $e )
{
$ERROR = sprintf( "发送邮件消息时在第 %d 行发生错误。", $e->getLine() ) . $e->getMessage();
return(
false );
}
}
[email protected]
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