当前位置: 首页 > news >正文

PHP Swoole Client

PHP常用socket创建TCP连接,使用CURL创建HTTP连接,为了简化操作,Swoole提供了Client类用于实现客户端功能,并增加了异步非阻塞模式,让用户在客户端也能使用事件循环。

作为客户端使用,Swoole Client可以在FPM环境下或 Apache中使用,但不允许使用Async异步模式,只能使用同步非阻塞模式,异步非阻塞模式仅限CLI模式下使用。

Client提供了TCP/UDP socket的客户端的封装代码,使用时仅需new Swoole\Client。

Swoole的socket客户端对比PHP提供的stream族函数有什么优势呢?

stream函数存在超时设置的陷阱和Bug,一旦没有处理好将会导致服务器长时间阻塞。
stream和fread有8192长度限制,无法支持UDP大包。
swoole_client客户端支持waitall,在知道包长度的情况下可以一次取完不必循环获取。
swoole_client支持UDP的connect解决了UDP串包的问题
swoole_client是纯C的代码
swoole_client支持异步非阻塞回调
构造方法 constructor
Swoole的Client功能封装为一个swoole_client类,可通过new swoole_client来创建一个客户端实例。

原型
 

swoole_client->__construct(int $sock_type, int $is_async = SWOOLEL_SOCK_SYNC, string $key
);

参数
参数1:int $sock_type
$sock_type 表示socket类型,可使用swoole提供的宏来指定类型。

  • SWOOLE_TCP 创建TCP Socket
  • SWOOLE_TCP6 创建IPv6 TCP Socket
  • SWOOLE_UDP 创建UDP Socket
  • SWOOLE_UDP6 创建IPv6 UDP Socket
  • SWOOLE_SSL 开启SSL加密
  • SWOOLE_KEEP 开启连接复用

其中SWOOLE_SSL与SWOOLE_KEEP不能单独使用,需要与前四个选项共同作用。
 

// 创建并开启SSL加密的TCP客户端
$client = new swoole_client(SWOOLE_TCP | SWOOLE_SSL);

SWOOLE_KEEP

swoole_client支持在PHP-FPM或Apache中建立一个TCP长连接到服务器,当客户端启用SWOOLE_KEEP选项后,一个请求结束不会关闭socket,下一次再进行connect连接时会自动复用上次创建的连接。如果执行connect连接时发现连接已经 被服务器断开,那么connect将会创建新的连接。

// 创建一个可以在FPM中使用的长连接客户端

$client = new swoole_client(SWOOLE_TCP | SWOOLE_KEEP);


SWOOLE_KEEP建立TCP长连接有什么优势呢?

TCP长连接可以减少connect建立连接时的三次握手和close断开连接的四次挥手所带来的额外IO开销
降低服务器connect建立连接和close断开连接的次数
例如:在PHP-FPM模式下可以使用同步模式的swoole_client向后端发送数据,为了能够让不同的连接复用同一个客户端client,可以开启SWOOLE_KEEP选项并指定对应的key。这样对于同一个逻辑就不需要为每个请求都创建一个新的连接了。这里需要注意的是,虽然共用了同一个连接,但是每个请求仍然会创建一个新的swoole_client实例,只是这些实例底层会复用同一个TCP连接。因此,如果开启了SWOOLE_KEEP选项也就不能随便调用close关闭客户端,并且在使用时可使用isConnect方法来判断连接是否可用。

<?php
//获取参数
$data = isset($_GET["data"])&&!empty($_GET["data"]) ? $_GET["data"] : "";
//创建同步阻塞TCP客户端,并开启连接复用。
$host = "127.0.0.1";
$port = 9501;
$key = $host.":".$port;//默认使用IP:PORT作为长连接的key,具有相同key的连接会被复用。
$client = new swoole_client(SWOOLE_TCP | SWOOLE_KEEP, SWOOLE_SYNC, $key);
//判断客户端时已连接
if(!$client->isConnect()){$client->connect($host, $port);
}
//发送数据
$client->send($data);
//接收打印
echo $client->recv();


参数2:int $is_sync
$is_sync表示同步阻塞或异步非阻塞,默认为同步阻塞。模式不同决定了可以使用的API的不同。

SWOOLE_SOCK_SYNC

SWOOLE_SOCK_SYNC 表示创建一个同步阻塞客户端,默认设置。

swoole_client(SWOOLE_TCP, SWOOLE_SYNC, $key);


当设定swoole_client为同步模式后,可以像使用PHP的sockets扩展也一样使用swoole_client来创建socket连接。由于是同步阻塞模式,所以connect、recv、send这样的方法都会阻塞进程。相比较PHP的sockets扩展提供的方法,swoole_client的API更为简洁,使用起来更加方便。

<?php
/*** 创建同步阻塞模式下的TCP客户端* 同步阻塞模式下connect/send/recv会等待IO完成后再返回,服务端返回后才会向下执行。* 同步阻塞模式下并不会消耗CPU资源,IO操作未完成当前进程会自动转入sleep模式。* 当IO完成后操作系统会唤醒当前进程,继续向下执行代码。* */
$client = new swoole_client(SWOOLE_TCP);//连接到服务器
$host = "127.0.0.1";
$port = 9501;
$timeout = 1;//超过与服务器交互的超时秒数会自动断开
if(!$client->connect($host, $port, $timeout)){die("[connect] failed".PHP_EOL);
}//发送数据
$message = "hello world";
if(!$client->send($message)){die("[send] failed".PHP_EOL);
}//接收数据
if(!$data = $client->recv()){die("[recv] failed".PHP_EOL);
}
echo $data.PHP_EOL;//关闭连接
$client->close();


SWOOLE_SOCK_ASYNC

SWOOLE_SOCK_ASYNC 表示创建一个异步非阻塞客户端

需要通过on方法注册异步回调函数
多个swoole_client客户端可以嵌套回调
异步模式仅可用于CLI命令行模式

swoole_client(SWOOLE_TCP, SWOOLE_SOCK_ASYNC)


当设置swoole_client为异步模式后,swoole_client就不能再使用recv方法了,而是需要通过on方法提供指定的回调函数,然后在回调函数当中处理。

异步模式的swoole_client必须设置四种回调函数connect、receive、error、close,不能够缺省,否则在调用connect连接时会提示回调未设置。同样,因为已经有了onConnect回调,因此异步模式的swoole_client调用connect方法时不再阻塞,connect方法也只会返回true,此时需要在onConnect回调中确定连接成功,或者在onError回调中确定连接失败。

<?php
/*** 创建异步非阻塞模式下的TCP客户端* 必须设置onConnect、onError、onReceive、onClose* */
$client = new swoole_client(SWOOLE_TCP, SWOOLE_SOCK_ASYNC);//连接成功时回调
$client->on("connect", function(swoole_client $client){//向服务器发送数据$message = "hello world".PHP_EOL;$client->send($message);
});//数据接收时回调
$client->on("receive", function(swoole_client $client, $data){if(empty($data)){$client->close();}else{echo "[receive] $data".PHP_EOL;sleep(1);$client->send(time());}
});//连接失败时回调
$client->on("error", function(swoole_client $client){echo "[error] connection failed".PHP_EOL;
});//注册关闭连接时回调
$client->on("close", function(swoole_client $client){echo "[close] connection close".PHP_EOL;
});//连接到服务器
$host = "127.0.0.1";
$port = 9501;
$timeout = 0.5;//超过与服务器交互的超时秒数会自动断开
if(!$client->connect($host, $port, $timeout)){die("[connect] failed".PHP_EOL);
}


异步模式的swoole_client跟swoole_server一样以事件作为驱动,而无法发像同步模式一样来驱动。只要提供需要的事件就能过够处理逻辑,如swoole的定时器、事件循环等。

例如:实现客户端,每秒向服务器发送一个心跳包,在接收到终端输入的内容后,该客户端会将终端输入的内容发送给服务器。

服务器

$ vim server.php

<?php
//创建TCP服务器并设置IP和端口
$host = "0.0.0.0";
$port = 9501;
$serv = new swoole_server($host, $port);//设置服务器运行时配置
$configs = [];
$configs["worker_num"] = 2;//设置Worker工作进程数量
$configs["task_worker_num"] = 2;//设置Task异步任务的进程数量
$serv->set($configs);//Master主进程 当服务器启动时触发
$serv->on("start", function(swoole_server $serv){echo PHP_EOL."[start] master {$serv->master_pid} manager {$serv->manager_pid}".PHP_EOL;
});//Worker工作进程 当客户端有新TCP连接时触发
$serv->on("connect", function(swoole_server $serv, $fd, $reactor_id){echo PHP_EOL."[connect] worker {$serv->worker_pid} reactor {$reactor_id} client {$fd}".PHP_EOL;
});//Worker工作进程 当客户端连接向服务器发送数据时触发
$serv->on("receive", function(swoole_server $serv, $fd, $reactor_id, $data){echo "[receive] worker {$serv->worker_pid} reactor {$reactor_id} client {$fd} data:{$data}".PHP_EOL;if($data !== "PING"){//投递异步任务给TaskWorker异步任务进程,程序会立即返回向下执行后续代码。$task_id = $serv->task($data);echo "[receive] task {$task_id} data:{$data}".PHP_EOL;//向客户端文件描述符发送字符串信息$message = "success";$serv->send($fd, $message);echo "[receive] client {$fd} send:{$message}".PHP_EOL;}
});//TaskWorker任务进程 处理异步任务
$serv->on("task", function(swoole_server $serv, $task_id, $reactor_id, $data){echo "[task] task {$task_id} reactor {$reactor_id} data:{$data}".PHP_EOL;sleep(10);//模拟异步操作执行时长10秒//返回任务执行的结果$serv->finish("finish");
});//Worker进程 处理异步任务完成的结果
$serv->on("finish", function(swoole_server $serv, $task_id, $data){echo "[finish] worker {$serv->worker_pid} task {$task_id} data:{$data}".PHP_EOL;
});//Worker进程 监听断开连接时触发
$serv->on("close", function(swoole_server $serv, $fd, $reactor_id){//连接断开类型$disconnect_type = "client";//客户端主动断开if($reactor_id < 0){$disconnect_type = "server";//服务器主动断开}echo "[close] worker {$serv->manager_pid} client {$fd} disconnect {$disconnect_type}".PHP_EOL;
});//启动服务器
$serv->start();


客户端

$ vim client.php
<?php
class Client
{private $client;private $timer_id;/**构造函数 */public function __construct($host, $port, $timeout=1){//构建异步非阻塞客户端对象$this->client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);//绑定事件回调函数$this->client->on("Connect", [$this, "onConnect"]);$this->client->on("Receive", [$this, "onReceive"]);$this->client->on("Close", [$this, "onClose"]);$this->client->on("Error", [$this, "onError"]);//连接服务器$this->client->connect($host, $port, $timeout=1);}/**连接服务器 */public function connect($host, $port, $timeout=1){//连接服务器$fp = $this->client->connect($host, $port, $timeout);if(!$fp){echo "[connect] error{$fp->errCode} {$fp->errMsg}".PHP_EOL;return;}}/**连接成功回调 */public function onConnect($client){//将标准输入添加到swoole的事件监听中swoole_event_add(STDIN, function($fp){//读取标准输入$message = trim(fgets(STDIN));if(!empty($message)){//发送数据$this->client->send($message);}});//添加定时器,每秒向服务器发送一个心跳包$this->timer_id = swoole_timer_tick(1000, function(){$this->client->send("PING");});}public function send($message){$this->client->send($message);}public function onReceive(swoole_client $client, $data){echo "[receive] {$data}".PHP_EOL;}public function onClose(swoole_client $client){$data = json_encode($client);echo "[close] {$data}".PHP_EOL;//断开连接时清除定时器swoole_timer_clear($this->timer_id);}public function onError(swoole_client $client){$data = json_encode($client);echo "[error] {$data}".PHP_EOL;}
}
$client = new Client("127.0.0.1", 9501, 1);


参数3:string $key
$key 表示用于长连接的key,默认使用IP:PORT作为key,相同key的连接会被复用。

对象属性

<?php
$client = new swoole_client(SWOOLE_TCP, SWOOLE_ASYNC);
echo json_encode($client).PHP_EOL;

{"errCode":0,"sock":-1,"reuse":false,"reuseCount":0,"type":1025,"id":null,"setting":null
}


错误码 int swoole_client->errCode
当connect、send、recv、close失败时会自动设置$swoole_client->errCode的值,errCode的值等于Linux的errno,可以使用socket_strerror将错误码转换为错误信息。

$client->on("close", function(swoole_client $client){if(!$client->errCode){$error = socket_strerror($client->errCode);echo "error: {$error}".PHP_EOL;}echo "close".PHP_EOL;
});


Socket文件描述符 int swoole_client->sock
sock属性值为整型的socket文件描述符,可转换int作为数组的key。

// 在PHP代码中可以使用

$sock = fopen("php://fd/".$swoole_client->sock);

  • $client->sock属性值仅在$client->connect后才能取出,在未连接服务器之前此属性值为null。
  • 将swoole_client的socket转换为一个stream socket可调用fread、fwrite、fclose等函数进行操作。
  • swoole_server中的$fd文件描述符不能使用sock()方法转换,因为$fd文件描述符只是一个属于主进程的数字。

是否复用 bool swoole_client->reuse
reuse属性值表示连接是新连接的还是复用已存在的,是一个布尔值,需要与SWOOLE_KEEP配合使用。

例如:WebSocket客户端与服务器建立连接后需要进行握手,如果连接是复用的,就无需再次进行握手,直接发送WebSocket数据帧即可。

if($client->reuse){$client->send($data);
}


建立连接 connect
connect方法用于建立连接到远程服务器

原型

bool $server_client->connect(string $host, int $port, float $timeout = 0.5, int $flag = 0
);


参数
参数1:string $host 表示远程服务器的地址,swoole1.10.0+已支持自动异步解析域名即可直接传入域名。
参数2:int $port 表示远程服务器的端口
参数3:float $timeout 表示网络IO超时秒数,包括connect、send、recv,单位为秒并支持浮点数,默认0.5s即500ms。
参数4:int $flag

  • 在UDP类型时表示是否启用udp_connect设定此选项后将绑定$host与$port,此UDP将会丢弃非指定host/port的数据包。
  • 在TCP类型中$flag=1表示设置为非阻塞socket,connect会立即返回。如果将$flag设置为1则在send/recv前必须使用swoole_client_select来检测是否完成了连接。

模式
同步模式
connect方法在同步模式下会发生阻塞,直到连接成功并返回true。这个时候就可以向服务器发送数据或接收数据了。如果连接失败则会返回false。另外,同步TCP客户端在执行close之后,可以再次发起connect创建新连接到服务器。

if($client->connect($host, $port)){$client->send($message);
}else{echo "connect failed";
}


异步模式
异步模式下connect连接会立即返回true,但实际上连接并未建立,所以不能在connect后使用send。此时使用fsConnected()判断也是false。当连接创建成功后,系统会自动回调onConnect,此时才可以使用send方法向服务器发送数据。

异步客户端执行connect时会增加一次引用计数,当连接关闭时会减少引用计数。

版本

  • 小于swoole1.9.11版本中$timeout超时设置在异步客户端中是无效的,应用层需要使用Timer::after自行添加定时器来实现异步客户端的链接超时控制。
  • 大于等于swoole1.9.11版本中,底层会自动添加定时器,在规定的时间内未连接成功时,底层会触发onError连接失败事件,错误码为ETIMEOUT(110)。

失败重连
connect失败后如果希望重连一次,必须先进行close关闭旧的socket,否则会返回EINPROCESS错误,因为当前的socket正在连接服务器,客户端并不知道是否连接成功,所以无法再次执行connect。

调用close会关闭当前的socket,底层会重新创建新的socket来进行连接。

启用SWOOLE_KEEP长连接后,close调用的第一个参数需要设置为true来表示强行销毁长连接socket。

//连接失败
if($socket->connect($host, $port) === false){$socket->close(true);//关闭旧的socket$socket->connect($host, $port);//重连
}


UDP连接
UDP连接时默认底层并不会启用,一个UDP客户端执行连接时,底层在创建socket后会立即返回成功,此时的socket绑定的地址为0.0.0.0,任何其它对端均可向此端口发送数据包。

$client->connect("192.168.1.100", 9502)


此时操作系统会为客户端socket随机分配一个端口,其它机器可向这个端口发送数据包。

未开启UDP连接时调用getsockname返回的host为0.0.0.0。

将connect的第四项参数$flag设置为1时将启用UDP连接。

$client->connect("192.168.1.100", 9501, 1, 1)


此时将会绑定客户端和服务器,底层会根据服务器的地址来绑定socket绑定的地址,例如连接了192.168.1.100,当前socket会被绑定到192.168.1.*的本地机器上。启用UDP连接后客户端将不再接收其它主机向此端口发送的数据包。

发送数据 send
send方法用于建立连接后发送数据到远程服务器

原型

int $swoole_client->send(string $data);


参数
参数:string $data 发送的数据,格式为字符串,支持二进制。

返回
成功发送返回已发送数据的长度
失败返回false,并设置$swoole_client->errCode错误码。
模式
1.同步

  • 发送的数据没有长度闲置
  • 发送的数据太多时socket缓存区塞满,底层会阻塞等待可写。

2.异步

  • 发送数据的长度收到socket_buffer_size限制
  • 如果socket缓存区已满,swoole的处理逻辑参考swoole_event_write。

注意

  • 如果没有执行连接connect直接调用send会触发PHP警告

接收数据 recv
recv方法用于从服务器接收数据

原型
swoole1.7.22-

string $swoole_client->recv(int $size = 655335, bool $waitall = 0)


swoole1.7.22+

string $swoole_client->recv(int $size = 65535, int $flag = 0);


swoole1.7.22版本后,将原来第二个参数$waitall参数修改为$flags可以接收一些特殊的socket接收设置,为了兼容旧的接口,如果$flag = 1表示 $flag = swoole_client::MSG_WAITALL。

$client->recv(8192, swoole_client::MSG_PEEK | swoole_client::MSG_WAITALL);


参数
int $size 表示接收数据的缓存区最大长度,此参数设置过大会占用较大内存。
bool $waitall 表示是否等待所有数据到达后返回
如果设置了$waitall就必须设定准确的$size否则会一直等待,直到接收的数据长度达到$size。如果未设置$waitall = true时$size最大未64K,如果设置了错误的$size将会导致recv超时而返回false。
 

返回
成功:成功接收到数据则返回字符串
失败:返回false需设置错误码$client->errCode属性
连接关闭:返回空字符串
 

EOL/Length
如果客户端启用了EOF/Length检测后,无需设置$size和$waitall参数,扩展层会返回完整的数据包或返回false。当接收到错误的包头或包头中长度超过package_max_length设置时,recv会返回空字符串,PHP代码中应当关闭此连接。

关闭连接 close
close用于关闭客户端连接,操作成功后返回true。当swoole_client客户端连接被close关闭后不要再次发起连接close。正确的做法是销毁当前的swoole_client,然后再重新创建一个swoole_client并发起新的连接。

bool $swoole_client->close(bool $force = false);


参数:bool $force 表示是否强制关闭连接,可用于关闭SWOOLE_KEEP长连接。
注意:swoole_client对象在析构时会自动关闭

异步非阻塞客户端close关闭时会立即关闭连接,如果发送队列中仍然有数据底层会丢弃。所以请勿在大量发送数据后立即close关闭,否则发送的数据未必能真正到达服务器端。

服务器

$ vim server.php


 

<?php
//创建TCP服务器并设置IP和端口
$host = "0.0.0.0";
$port = 9501;
$server = new swoole_server($host, $port);//设置服务器运行时配置
$configs = [];
$configs["worker_num"] = 2;//设置Worker工作进程数量
$configs["task_worker_num"] = 2;//设置Task异步任务的进程数量
$server->set($configs);//Master主进程 当服务器启动时触发
$server->on("start", function(swoole_server $server){echo PHP_EOL."[start] master {$server->master_pid} manager {$server->manager_pid}".PHP_EOL;
});//Worker工作进程 当客户端有新TCP连接时触发
$server->on("connect", function(swoole_server $server, $fd, $reactor_id){echo PHP_EOL."[connect] worker {$server->worker_pid} reactor {$reactor_id} client {$fd}".PHP_EOL;
});//Worker工作进程 当客户端连接向服务器发送数据时触发
$server->on("receive", function(swoole_server $server, $fd, $reactor_id, $data){echo "[receive] worker {$server->worker_pid} reactor {$reactor_id} client {$fd} data:{$data}".PHP_EOL;if($data !== "PING"){//投递异步任务给TaskWorker异步任务进程,程序会立即返回向下执行后续代码。$task_id = $server->task($data);echo "[receive] task {$task_id} data:{$data}".PHP_EOL;//向客户端文件描述符发送字符串信息$message = "success";$server->send($fd, $message);echo "[receive] client {$fd} send:{$message}".PHP_EOL;}
});//TaskWorker任务进程 处理异步任务
$server->on("task", function(swoole_server $server, $task_id, $reactor_id, $data){echo "[task] task {$task_id} reactor {$reactor_id} data:{$data}".PHP_EOL;sleep(10);//模拟异步操作执行时长10秒//返回任务执行的结果$server->finish("finish");
});//Worker进程 处理异步任务完成的结果
$server->on("finish", function(swoole_server $server, $task_id, $data){echo "[finish] worker {$server->worker_pid} task {$task_id} data:{$data}".PHP_EOL;
});//Worker进程 监听断开连接时触发
$server->on("close", function(swoole_server $server, $fd, $reactor_id){//连接断开类型$disconnect_type = "client";//客户端主动断开if($reactor_id < 0){$disconnect_type = "server";//服务器主动断开}echo "[close] worker {$server->manager_pid} client {$fd} disconnect {$disconnect_type}".PHP_EOL;
});//启动服务器
$server->start();

客户端

$ vim client.php

客户端发送4MB的数据,实际传输可能需要一段时间,此时如果立即进行close关闭操作,可能只有小部分数据传输成功,大部分数据在发送队列中排队等待发送,close关闭时会丢失这些数据。

<?php
$client = new swoole_client(SWOOLE_TCP, SWOOLE_ASYNC);
$client->on("connect", function(swoole_client $client){echo "connect".PHP_EOL;//将标准输入添加到事件监听中swoole_event_add(STDIN, function($fp) use($client){$msg = trim(fgets(STDIN));$client->send($msg);});
});
$client->on("receive", function(swoole_client $client, $data){echo "receive:{$data}".PHP_EOL;$client->send(str_repeat("X", 1024*1024*4).PHP_EOL);$client->close();
});
$client->on("error", function(swoole_client $client){echo "error".PHP_EOL;
});
$client->on("close", function(swoole_client $client){echo "close".PHP_EOL;
});
$client->connect("127.0.0.1", 9501);    


解决方案

配合使用onBufferEmpty等待发送队列为空时进行close操作
 

<?php
$client = new swoole_client(SWOOLE_TCP, SWOOLE_ASYNC);
$client->on("connect", function(swoole_client $client){echo "connect".PHP_EOL;//将标准输入添加到事件监听中swoole_event_add(STDIN, function($fp) use($client){$msg = trim(fgets(STDIN));$client->send($msg);});
});
$client->on("receive", function(swoole_client $client, $data){echo "receive:{$data}".PHP_EOL;$client->send(str_repeat("X", 1024*1024*4).PHP_EOL);$client->close();
});
$client->on("error", function(swoole_client $client){echo "error".PHP_EOL;
});
$client->on("close", function(swoole_client $client){echo "close".PHP_EOL;
});
//配合使用onBufferEmpty等待发送队列为空时进行关闭close操作
$client->on("bufferEmpty", function(swoole_client $client){$client->close();
});
$client->connect("127.0.0.1", 9501);    

  • 协议设计为onReceive收到数据后主动关闭连接,发送数据时对端主动关闭连接。

相关文章:

PHP Swoole Client

PHP常用socket创建TCP连接&#xff0c;使用CURL创建HTTP连接&#xff0c;为了简化操作&#xff0c;Swoole提供了Client类用于实现客户端功能&#xff0c;并增加了异步非阻塞模式&#xff0c;让用户在客户端也能使用事件循环。 作为客户端使用&#xff0c;Swoole Client可以在F…...

《QDebug 2023年12月》

一、Qt Widgets 问题交流 1. 二、Qt Quick 问题交流 1.Q_REVISION 标记的信号槽或者 REVISION 标记的属性&#xff0c;在子类中访问 Q_REVISION 是 Qt 用来做版本控制的一个宏。以 QQuickWindow 为例&#xff0c;继承后去访问 REVISION 标记的 opacity 属性或者 Q_REVISION…...

sklearn 中matplotlib编制图表

代码 # 导入pandas库&#xff0c;并为其设置别名pd import pandas as pd import matplotlib.pyplot as plt# 使用pandas的read_csv函数读取名为iris.csv的文件&#xff0c;将数据存储在iris_data变量中 iris_data pd.read_csv(data/iris.txt,sep\t)# 使用groupby方法按照&quo…...

【Docker-Dev】Mac M2 搭建docker的redis环境

Redis的dev环境docker搭建 1、前言2、官方文档重点信息提取2.1、创建redis实例2.2、使用自己的redis.conf文件。 3、单机版redis搭建4、redis集群版4.1、一些验证4.2、一些问题 结语 1、前言 本文主要针对M2下&#xff0c;相应进行开发环境搭建&#xff0c;然后做一个文档记录…...

docker +gitee+ jenkins +maven项目 (一)

jenkins环境和插件配置 文章目录 jenkins环境和插件配置前言一、环境版本二、jenkins插件三、环境安装总结 前言 现在基本都是走自动化运维&#xff0c;想到用docker 来部署jenkins &#xff0c;然后jenkins来部署java代码&#xff0c;做到了开箱即用&#xff0c;自动发布代码…...

IDEA 开发中常用的快捷键

目录 Ctrl 的快捷键 Alt 的快捷键 Shift 的快捷键 Ctrl Alt 的快捷键 Ctrl Shift 的快捷键 其他的快捷键 Ctrl 的快捷键 Ctrl F 在当前文件进行文本查找 &#xff08;必备&#xff09; Ctrl R 在当前文件进行文本替换 &#xff08;必备&#xff09; Ctrl Z 撤…...

Ubuntu Desktop 死机处理

Ubuntu Desktop 死机处理 当 Ubuntu Desktop 死机时&#xff0c;除了长按电源键重启&#xff0c;还可以使用如下两种方式处理。 方式1&#xff1a;ctrlaltFn 使用 ctrl alt F3~F6: 切换到其他 tty 命令行。 执行 top 命令查看资源占用最多的进程&#xff0c;然后使用 kill…...

Hermite矩阵

Hermite矩阵 文章目录 Hermite矩阵一、正规矩阵【定义】A^H^矩阵【定理】 A^H^的运算性质【定义】正规矩阵、特殊的正规矩阵【定理】与正规矩阵酉相似的矩阵也是正规矩阵【定理】正规的上(下)三角矩阵必为对角矩阵【定义】复向量的内积【定理】Schmitt正交化 二、酉矩阵&#x…...

HTML 实操试题(二)

创建一个简单的HTML文档&#xff1a; 包含<!DOCTYPE html>声明。包含<html>标签&#xff0c;并设置lang属性为英语。包含<head>标签&#xff0c;其中包含<meta charset"UTF-8">和一个自定义的页面标题。包含<body>标签&#xff0c;其…...

MongoDB 面试题

MongoDB 面试题 1. 什么是MongoDB&#xff1f; MongoDB是一种非关系型数据库&#xff0c;被广泛用于大型数据存储和分布式系统的构建。MongoDB支持的数据模型比传统的关系型数据库更加灵活&#xff0c;支持动态查询和索引&#xff0c;也支持BSON格式的数据存储&#xff0c;这…...

LeetCode 1154. 一年中的第几天:2023年最后一道每日一题

【LetMeFly】1154.一年中的第几天&#xff1a;2023年最后一道每日一题 力扣题目链接&#xff1a;https://leetcode.cn/problems/day-of-the-year/ 给你一个字符串 date &#xff0c;按 YYYY-MM-DD 格式表示一个 现行公元纪年法 日期。返回该日期是当年的第几天。 示例 1&…...

《深入理解JAVA虚拟机笔记》OutOfMemoryError 异常

在《Java 虚拟机规范》的规定里&#xff0c;除了程序计数器外&#xff0c;虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError &#xff08;下文称 OOM&#xff09;异常的可能。 Java堆溢出 Java 堆用于储存对象实例&#xff0c;我们只要不断地创建对象&#xff0c;并…...

R306指纹识别模块指令系统

一&#xff1a;指令集 1. GR_GetImage 指令代码&#xff1a;01H 功能&#xff1a;从传感器上读入图像存于图像缓冲区 2. GR_GenChar 指令代码&#xff1a;02H 功能&#xff1a;根据原始图像生成指纹特征存于 CharBuffer1 或 CharBuffer2 3. GR_Match 指令代码&#xff…...

redis的搭建及应用(三)-Redis主从配置

Redis主从配置 为提升Redis的高可用性&#xff0c;需要搭建多个Redis集群以保证高可用性。常见搭建方式有&#xff1a;主从&#xff0c;哨兵集群等&#xff0c;本节我们搭建一主二从的多Redis架构。 redis主从安装1主2从的方式配置&#xff0c;以端口号为redis的主从文件夹。 主…...

Java学习,一文掌握Java之SpringBoot框架学习文集(1)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…...

javaWeb学生信息管理系统2

一、学生信息管理系统SIMS 一款基于纯Servlet技术开发的学生信息管理系统&#xff08;SIMS&#xff09;&#xff0c;在设计中没有采用SpringMVC和Spring Boot等框架。系统完全依赖于Servlet来处理HTTP请求和管理学生信息&#xff0c;实现了信息的有效存储、检索和更新&#xf…...

Linux Shell 019-文本行处理工具sed

Linux Shell 019-文本行处理工具sed 本节关键字&#xff1a;Linux、Bash Shell、文本行处理工具 相关指令&#xff1a;sed、 sed介绍 sed是Stream Editor&#xff08;流编辑器&#xff09;的缩写&#xff0c;简称流编辑器&#xff1b;用来处理文件的。sed是一行一行读取文件…...

Ubuntu中fdisk磁盘分区并挂载、扩容逻辑卷

Ubuntu中fdisk磁盘分区并挂载、扩容逻辑卷 一&#xff1a;fdisk磁盘分区并挂载1.查看磁盘分区信息2.分区3.强制系统重新读取分区(避免重启系统)4.格式化分区5.创建挂载目录6.设置开机自动挂载&#xff1a;7.验证并自动挂载(执行了该命令不需要重启系统)8.查看挂载007.异常情况处…...

【leetcode】栈与队列总结

本文内容来自于代码随想录 栈 用栈实现队列 两个栈实现队列。思路&#xff1a;两个栈分别表示入栈和出栈。 入队&#xff1a;直接入栈出队&#xff1a; a. 出栈为空&#xff0c;先把入栈中的元素全部放到出栈中&#xff08;相当于反过来&#xff0c;这样在出栈的时候先进的元…...

[EFI]HP Spectre 13 v102nl电脑 Hackintosh 黑苹果efi引导文件

硬件型号驱动情况主板 HP Spectre 13 v102nl 处理器Intel Core i7-7500U (7th gen - Kaby Lake)已驱动内存8 GB LPDDR3-1866 SDRAM已驱动硬盘512 GB Toshiba NVMe™ M.2 SSD已驱动显卡Intel HD Graphics 620已驱动声卡Conexant CX8200 (0x2008)已驱动网卡I1211 Gigabit Etherne…...

【Pytorch】学习记录分享8——PyTorch自然语言处理基础-词向量模型Word2Vec

【Pytorch】学习记录分享7——PyTorch自然语言处理基础-词向量模型Word2Vec 1. 词向量模型Word2Vec)1. 如何度量这个单词的&#xff1f;2.词向量是什么样子&#xff1f;3.词向量对应的热力图&#xff1a;4.词向量模型的输入与输出![在这里插入图片描述](https://img-blog.csdni…...

【Kotlin 】协程

Kotlin协程 背景定义实践GlobalScope.launchrunBlocking业务实践 背景 在项目实践过程中&#xff0c;笔者发现很多异步或者耗时的操作&#xff0c;都使用了Kotlin中的协程&#xff0c;所以特地研究了一番。 定义 关于协程&#xff08;Coroutine&#xff09;&#xff0c;其实…...

用Xshell连接虚拟机的Ubuntu20.04系统记录。虚拟机Ubuntu无法上网。本机能ping通虚拟机,反之不能。互ping不通

先别急着操作&#xff0c;看完再试。 如果是&#xff1a;本机能ping通虚拟机&#xff0c;反之不能。慢慢看到第8条。 如果是&#xff1a;虚拟机不能上网&#xff08;互ping不通&#xff09;&#xff0c;往下一直看。 系统是刚装的&#xff0c;安装步骤&#xff1a;VMware虚拟机…...

人机对话--关于意识机器

人机对话–关于意识机器 这段内容是我和《通义千问》的对话。这本身展示的是人工智能的效果&#xff0c;同时这里面的内容也有人工智能相关&#xff0c;与各位分享。 我&#xff1a;阿尼尔赛斯 《意识机器》这本书写的是什么&#xff1f; 通义千问&#xff1a; 阿尼尔赛斯教…...

八股文打卡day16——计算机网络(16)

面试题&#xff1a;TCP连接是如何确保可靠性的&#xff1f; 我的回答&#xff1a; 1.数据分块控制。应用数据被分成被认为最适合传输的数据块大小&#xff0c;再发送到传输层&#xff0c;数据块被称为数据报文段或数据段。 2.序列号和确认应答。TCP为每一个数据包分配了一个序…...

Java Object浅克隆深克隆

对象克隆 把A对象的属性值完全拷贝给B对象&#xff0c;也叫对象拷贝&#xff0c;对象复制。 实现Cloneable接口&#xff0c;表示当前类的对象就可以被克隆&#xff0c;反之&#xff0c;表示当前类的对象就不能克隆。 如果一个接口里面没有抽象方法&#xff0c;表示当前的接口…...

概率的 50 个具有挑战性的问题 [8/50]:完美的桥牌

一、说明 我最近对与概率有关的问题产生了兴趣。我偶然读到了弗雷德里克莫斯特勒&#xff08;Frederick Mosteller&#xff09;的《概率论中的五十个具有挑战性的问题与解决方案》&#xff09;一书。我认为创建一个系列来讨论这些可能作为面试问题出现的迷人问题会很有趣。每篇…...

自动驾驶学习笔记(二十四)——车辆控制开发

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo开放平台9.0专项技术公开课》免费报名—>传送门 文章目录 前言 控制算法 控制标定 控制协议…...

【起草】【第十二章】定制ChatGPT数字亲人

身为普普通通的我们&#xff0c;不知道亲人们在哪一天就要离开这个世界 &#xff1f; 作为普普通通的程序员&#xff0c;我们可以为我们的亲人做点什么 &#xff1f; 让他们以数字资产形式留在人世间 ? 对话&#xff5c;6岁女孩病逝捐器官&#xff0c;妈妈&#xff1a;她去…...

MySQL数据库索引

索引的定义 索引是一个排序的列表&#xff0c;包含索引字段的值和其对应的行记录的数据所在的物理地址 索引的作用 加快表的查询速度&#xff0c;还可以对字段排序 索引的副作用 会额外占用磁盘空间&#xff1b;更新包含索引的表会花费更多的时间&#xff0c;效率会更慢 …...

【LLM 】7个基本的NLP模型,为ML应用程序赋能

在上一篇文章中&#xff0c;我们已经解释了什么是NLP及其在现实世界中的应用。在这篇文章中&#xff0c;我们将继续介绍NLP应用程序中使用的一些主要深度学习模型。 BERT 来自变压器的双向编码器表示&#xff08;BERT&#xff09;由Jacob Devlin在2018年的论文《BERT:用于语言…...

数字人私人定制

数字人是什么&#xff1f; 在回答这个问题之前&#xff0c;我们先回答另一个问题&#xff0c;人如何与人工智能交流&#xff1f;目前可以通过文字、语音、电脑屏幕、手机屏幕、平板、虚拟现实设备等和人工智能交流&#xff0c;为了得到更好的交流体验&#xff0c;人工智能必然…...

CollectionUtils

使用 CollectionUtils 类的常用方法 在Java开发中&#xff0c;我们经常需要对集合进行各种操作&#xff0c;而Apache Commons Collections库提供了一个方便的工具类 CollectionUtils&#xff0c;其中包含了许多实用的方法。在这篇博客中&#xff0c;我们将深入了解一些常用的方…...

很想写一个框架,比如,spring

很想写一个框架&#xff0c;比如&#xff0c;spring。 原理很清楚&#xff0c;源码也很熟悉。 可惜力不从心&#xff0c;是不是可以找几个小弟一起做。...

Java集合/泛型篇----第五篇

系列文章目录 文章目录 系列文章目录前言一、说说LinkHashSet( HashSet+LinkedHashMap)二、HashMap(数组+链表+红黑树)三、说说ConcurrentHashMap前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通…...

ACES 增强版不丹水稻作物地图(2016-2022 年)

ACES 增强版不丹水稻作物地图&#xff08;2016-2022 年&#xff09; 用于改善粮食安全决策的 2016-2022 年年度作物类型稻米地图仍然是不丹的一项挑战。这些地图是与不丹农业部和 SERVIR 合作开发的。通过专注于发展不丹的科学、技术、工程和数学 (STEM)&#xff0c;我们共同开…...

【Spark精讲】一文讲透Spark宽窄依赖的区别

宽依赖窄依赖的区别 窄依赖&#xff1a;RDD 之间分区是一一对应的宽依赖&#xff1a;发生shuffle&#xff0c;多对多的关系 宽依赖是子RDD的一个分区依赖了父RDD的多个分区父RDD的一个分区的数据&#xff0c;分别流入到子RDD的不同分区特例&#xff1a;cartesian算子对应的Car…...

nacos2.3.0配置中心问题处理

问题&#xff1a;Error to process server push response: {"headers":{},"abilityTable":{"supportPersistentInstanceByGrpc":true},"module":"internal"} 处理办法&#xff1a; 将pom.xml中 <!-- nacos服务注册/发…...

Apollo自动驾驶系统:实现城市可持续交通的迈向

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 ChatGPT体验地址 文章目录 前言引言&#xff1a;1. 什么是微服务架构&#xff1f;2. 微服务架构的组成要素3. 微服务架构的挑战和解决方案4. 微服务架构的可扩展性和弹性 第二部分&#x…...

【WPF.NET开发】附加事件

本文内容 先决条件附加事件语法WPF 如何实现附加事件附加事件方案处理附加事件定义自定义附加事件引发 WPF 附加事件 Extensible Application Markup Language (XAML) 定义了一种语言组件和称为附加事件的事件类型。 附加事件可用于在非元素类中定义新的 路由事件&#xff0c…...

java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队

背景 近期参与了一个攻坚项目&#xff0c;前期因为其他流程原因&#xff0c;测试时间已经耽搁了好几天了&#xff0c;本以为已经解决了卡点&#xff0c;后续流程应该顺顺利利的&#xff0c;没想到 人在地铁上&#xff0c;bug从咚咚来~ 没有任何修改的服务接口&#xff0c;抛出…...

【pynput】鼠标行为追踪并模拟

文章目录 前言基本思路安装依赖包实时鼠标捕获捕获鼠标位置捕获鼠标事件记录点击内容效果图 实时按键捕获控制按键操作捕获按键事件组合键记录区间设置 用户操作记录与回溯基本思路完整代码效果图 利用本文内容从事的任何犯法行为和开发与本人无关&#xff0c;请理性利用技术服…...

docker小白第十天

redis集群主从容错切换案例 3主3从的redis集群&#xff0c;某个主机宕机了&#xff0c;需要对应的从机补位。 docker exec -it redis-node-1 /bin/bash # 进入容器1的命令行 redis-cli -p 6381 # 进入节点1的命令行 cluster nodes # 查看集群信息可以看到1号和6号对应是主从关…...

Apache SSI 远程命令执行漏洞

一、环境搭建 二、访问upload.php 三、写shell <!--#exec cmd"id" --> 四、访问 如图所示&#xff0c;即getshell成功&#xff01;​...

阿里云30个公共云地域、89个可用区、5个金融云和政务云地域

阿里云基础设施目前已面向全球四大洲&#xff0c;公共云地域开服运营30个公共云地域、89个可用区&#xff0c;此外还拥有5个金融云、政务云地域&#xff0c;并且致力于持续的新地域规划和建设&#xff0c;从而更好的满足用户多样化的业务和场景需求。伴随着基础设施的加速投入和…...

Linux驱动开发之杂项设备注册和Linux2.6设备注册

目录 一、杂项设备注册 杂项设备注册简介 杂项设备注册特点: 杂项设备注册相关API misc_register() misc_deregister() 杂项设备注册相关例程 例程简介 源码分享 二、Linux 2.6设备注册 Linux2.6设备注册简介 Linux 2.6设备注册特点 Linux2.6设备注册流程 ​Linu…...

javafx写一个文档编辑器

文本编辑器是一种用于编辑纯文本文件的工具。它具有基本的文本编辑功能,如插入、删除、复制、粘贴等。文本编辑器通常不具备格式化文本、排版和图形编辑等高级功能,专注于纯文本的编辑。常见的文本编辑器包括记事本(Notepad)、Sublime Text、Visual Studio Code、Atom、Emacs…...

PHP与Angular详细对比 帮助你选择合适的项目技术

开发可有效扩展并提供诺克斯堡级安全性的Web应用程序和网站是每个开发人员的梦想。而使用这样的产品是每个用户的愿望。因此&#xff0c;为您的项目选择最合适和可靠的技术非常关键。 虽然PHP和Angular是完全不同的技术——PHP与JavaScript是一个更恰当的比较——但它们都广泛…...

基于立锜RTQ7882,支持全协议及DP显示功能的PD快充方案

在上一篇文章【基于RTQ7882的车载PD快充方案 - 大大通 &#xff08;wpgdadatong.com&#xff09;】中&#xff0c;已经对立锜科技&#xff08;Richtek&#xff09;及主打产品RTQ7882的基本功能作了介绍。 本文将分享RTQ7882近期新增的功能&#xff0c;以及其Cost Down版本。 旨…...

2023-12-25 LeetCode每日一题(不浪费原料的汉堡制作方案)

2023-12-25每日一题 一、题目编号 1276. 不浪费原料的汉堡制作方案二、题目链接 点击跳转到题目位置 三、题目描述 圣诞活动预热开始啦&#xff0c;汉堡店推出了全新的汉堡套餐。为了避免浪费原料&#xff0c;请你帮他们制定合适的制作计划。 给你两个整数 tomatoSlices …...