# send
## 说明:
~~~
mixed $connection->send(mixed $data [,$raw = false])
~~~
向客户端发送数据
>[danger] 请一点要注意,如果不同协程同时调用send方法。协程A等待epoll时间唤醒写入协程,协程B如果这个时候再去保存写入协程,会引起程序致命错误。所以尽量在onMessage中进行send操作
## 参数
`$data`
要发送的数据,如果在初始化Worker类时指定了协议,则会自动调用协议的encode方法,完成协议打包工作后发送给客户端
`$raw`
是否发送原始数据,即不调用协议的encode方法,默认是false,即自动调用协议的encode方法
## 返回值
true 表示数据已经成功写入到该连接的操作系统层的socket发送缓冲区
false 表示发送失败,失败原因可能是客户端连接已经关闭,或者该连接的应用层发送缓冲区已满
## 注意
send返回`true`,仅仅代表数据已经成功写入到该连接的操作系统socket发送缓冲区,并不意味着数据已经成功的发送给对端socket接收缓冲区,更不意味着对端应用程序已经从本地socket接收缓冲区读取了数据。**不过即便如此,只要send不返回false并且网络没有断开,而且客户端接收正常,数据基本上可以看做100%能发到对方的。**
由于socket发送缓冲区的数据是由操作系统异步发送给对端的,操作系统并没有给应用层提供相应确认机制,所以**应用层**无法得知socket发送缓冲区的数据何时开始发送,**应用层**更无法得知socket发送缓冲区的数据是否发送成功。基于以上原因workerman无法直接提消息确认接口。
如果业务需要保证每个消息客户端都收到,可以在业务上增加一种确认机制。确认机制可能根据业务不同而不同,即使同样的业务确认机制也可以有多种方法。
例如聊天系统可以用这样的确认机制。把每条消息都存入数据库,每条消息都有一个是否已读字段。客户端每收到一条消息向服务端发送一个确认包,服务端将对应消息置为已读。当客户端连接到服务端时(一般是用户登录或者断线重连),查询数据库是否有未读的消息,有的话发给客户端,同样客户端收到消息后通知服务端已读。这样可以保证每个消息对方都能收到。当然开发者也可以用自己的确认逻辑。
## 范例
~~~
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
Warriorman\Worker::rename();
$worker = new Worker('tcp://0.0.0.0:8484');
$worker->protocol = "\Workerman\Protocols\Websocket";
$worker->onMessage = function($connection, $data)
{
// 会自动调用\Workerman\Protocols\Websocket::encode打包成websocket协议数据后发送
$connection->send("hello\n");
};
// 运行worker
Worker::runAll();
~~~
- 序言
- 启动停止
- 简单的开发示例
- 性能测试
- 性能测试-数据库
- 通讯协议
- Coroutine类
- create
- getCid
- yield
- resume
- sleep
- wait
- getTotalNum
- isExist
- defer
- Runtime类
- Worker类
- 构造函数
- 属性
- workerId
- id
- name
- protocol
- transport
- reusePort
- backlog
- connections
- stdoutFile
- pidFile
- logFile
- user
- reloadable
- daemonize
- globalEvent
- 回调属性
- onWorkerStart
- onWorkerReload
- onConnect
- onMessage
- onClose
- onBufferFull
- onBufferDrain
- onError
- 方法
- rename
- runAll
- stopAll
- listen
- TcpConnection类
- 属性
- id
- protocol
- worker
- maxSendBufferSize
- defaultMaxSendBufferSize
- defaultMaxPackageSize
- 方法
- set
- send
- getRemoteIp
- getRemotePort
- close
- destroy
- pauseRecv
- resumeRecv
- pipe
- Timer定时器类
- add
- del
- 定时器注意事项
- Channel类
- 构造方法
- push
- pop
- length
- isEmpty()