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() 不一定写入给定缓冲区中的所有字节。有效的是,根据网络缓冲区等,只写入一定数量的数据,甚至是一个字节,尽管您的缓冲区更大。您必须小心,不要无意中忘记传输剩余的数据。

参见

添加注释

用户贡献的注释 8 notes

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

如果消息不大,它们将使用单个 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;
}

}
?>
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 "传输不完整";
}
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 );
}
}
gtk at linux dot online dot no
21 年前
来自 http://www.manualy.sk/sock-faq/unix-socket-faq-2.html
read() 等同于 flags 参数为 0 的 recv()。flags 参数的其他值会改变 recv() 的行为。类似地,write() 等同于 flags == 0 的 send()。
webmaster at you-are-infected dot com
17 年前
如果你像使用 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"));
?>
导致服务器停止发送任何数据。

我希望这能节省很多时间。我花了大约两天时间才发现这是问题所在;)
jean at briskula dot si
13 年前
一些客户端(例如 Flash 的 XMLSocket)在收到新行之前不会触发读取事件。

<?php
/*
* 写入套接字
* 在末尾添加一个新行和空字符
* 一些客户端在收到新行之前不会读取
*
* 如果数据被截断,尝试发送其余数据
*/
function write(&$sock,$msg) {
$msg = "$msg\n\0";
$length = strlen($msg);
while(
true) {
$sent = socket_write($sock,$msg,$length);
if(
$sent === false) {
return
false;
}
if(
$sent < $length) {
$msg = substr($msg, $sent);
$length -= $sent;
print(
"消息被截断: 重新发送: $msg");
} else {
return
true;
}
}
return
false;
}
?>
masterwaster at gmail dot com
15 年前
嗨,
如果你遇到了和我一样的問題

<?php
@socket_write($xd, "Good Bye!\n\r");
@
socket_shutdown($xd, 2);
@
socket_close($xd);
?>

将不会发送 "Good Bye!\n\r" 到打开的套接字。

但如果你放一个
usleep 或者类似 echo "";
在 write 和 shutdown 之间,它就能工作。
divinity76 at gmail dot com
9 年前
function AddTCPChecksum(&$data){
//随意添加一些 strlen($data)>65535 的错误处理...
$data=pack("v",strlen($data)).$data;
}
To Top