主頁 > 後端開發 > PHP Swoole長連接常見問題

PHP Swoole長連接常見問題

2020-09-24 01:36:10 後端開發

連接失效問題
例子
其中,Redis常見的報錯就是:

配置項:timeout
報錯資訊:Error while reading line from the server
Redis可以配置如果客戶端經過多少秒還不給Redis服務器發送資料,那么就會把連接close掉,

MySQL常見的報錯:

配置項:wait_timeout & interactive_timeout
報錯資訊:has gone away
和Redis服務器一樣,MySQL也會定時的去清理掉沒用的連接,

如何解決
1、用的時候進行重連

2、定時發送心跳維持連接

用的時候進行重連
優點是簡單,缺點是面臨短連接的問題,

定時發送心跳維持連接
推薦,

如何維持長連接

tcp協議中實作的tcp_keepalive

 

作業系統底層提供了一組tcp的keepalive配置:

 1 tcp_keepalive_time (integer; default: 7200; since Linux 2.2)
 2 The number of seconds a connection needs to be idle before TCP
 3 begins sending out keep-alive probes. Keep-alives are sent only
 4 when the SO_KEEPALIVE socket option is enabled. The default
 5 value is 7200 seconds (2 hours). An idle connection is
 6 terminated after approximately an additional 11 minutes (9
 7 probes an interval of 75 seconds apart) when keep-alive is
 8 enabled.
 9  
10 Note that underlying connection tracking mechanisms and
11 application timeouts may be much shorter.
12  
13 tcp_keepalive_intvl (integer; default: 75; since Linux 2.4)
14 The number of seconds between TCP keep-alive probes.
15  
16 tcp_keepalive_probes (integer; default: 9; since Linux 2.2)
17 The maximum number of TCP keep-alive probes to send before
18 giving up and killing the connection if no response is obtained
19 from the other end.
20 8

Swoole底層把這些配置開放出來了,例如:

 1 ?php
 2  
 3 $server = new \Swoole\Server('127.0.0.1', 6666, SWOOLE_PROCESS);
 4  
 5 $server->set([
 6 'worker_num' => 1,
 7 'open_tcp_keepalive' => 1,
 8 'tcp_keepidle' => 4, // 對應tcp_keepalive_time
 9 'tcp_keepinterval' => 1, // 對應tcp_keepalive_intvl
10 'tcp_keepcount' => 5, // 對應tcp_keepalive_probes
11 ]);

其中:

1 'open_tcp_keepalive' => 1, // 總開關,用來開啟tcp_keepalive
2 'tcp_keepidle' => 4, // 4s沒有資料傳輸就進行檢測
3 // 檢測的策略如下:
4 'tcp_keepinterval' => 1, // 1s探測一次,即每隔1s給客戶端發一個包(然后客戶端可能會回一個ack的包,如果服務端收到了這個ack包,那么說明這個連接是活著的)
5 'tcp_keepcount' => 5, // 探測的次數,超過5次后客戶端還沒有回ack包,那么close此連接

 

我們來實戰測驗體驗一下,服務端腳本如下:

 1 <?php
 2  
 3 $server = new \Swoole\Server('127.0.0.1', 6666, SWOOLE_PROCESS);
 4  
 5 $server->set([
 6 'worker_num' => 1,
 7 'open_tcp_keepalive' => 1, // 開啟tcp_keepalive
 8 'tcp_keepidle' => 4, // 4s沒有資料傳輸就進行檢測
 9 'tcp_keepinterval' => 1, // 1s探測一次
10 'tcp_keepcount' => 5, // 探測的次數,超過5次后還沒有回包close此連接
11 ]);
12  
13 $server->on('connect', function ($server, $fd) {
14 var_dump("Client: Connect $fd");
15 });
16  
17 $server->on('receive', function ($server, $fd, $reactor_id, $data) {
18 var_dump($data);
19 });
20  
21 $server->on('close', function ($server, $fd) {
22 var_dump("close fd $fd");
23 });
24  
25 $server->start();

我們啟動這個服務器:

1 ~/codeDir/phpCode/hyperf-skeleton # php server.php

然后通過tcpdump進行抓包:

~/codeDir/phpCode/hyperf-skeleton # tcpdump -i lo port 6666
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

我們此時正在監聽lo上的6666埠的資料包,

然后我們用客戶端去連接它:

1 ~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666

此時服務端會列印出訊息:

~/codeDir/phpCode/hyperf-skeleton # php server.php
string(17) "Client: Connect 1"

tcpdump的輸出資訊如下:

1 01:48:40.178439 IP localhost.33933 > localhost.6666: Flags [S], seq 43162537, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 0,nop,wscale 7], length 0
2 01:48:40.178484 IP localhost.6666 > localhost.33933: Flags [S.], seq 1327460565, ack 43162538, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 9833698,nop,wscale 7], length 0
3 01:48:40.178519 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9833698 ecr 9833698], length 0
4 01:48:44.229926 IP localhost.6666 > localhost.33933: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0
5 01:48:44.229951 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0
6 01:48:44.229926 IP localhost.6666 > localhost.33933: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0
7 01:48:44.229951 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0
8 01:48:44.229926 IP localhost.6666 > localhost.33933: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0
9 // 省略了其他的輸出

我們會發現最開始的時候,會列印三次握手的包:

01:48:40.178439 IP localhost.33933 > localhost.6666: Flags [S], seq 43162537, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 0,nop,wscale 7], length 0
01:48:40.178484 IP localhost.6666 > localhost.33933: Flags [S.], seq 1327460565, ack 43162538, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 9833698,nop,wscale 7], length 0
01:48:40.178519 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9833698 ecr 9833698], length 0

然后,停留了4s沒有任何包的輸出,

之后,每隔1s左右就會列印出一組:

1 01:52:54.359341 IP localhost.6666 > localhost.43101: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9858736], length 0
2 01:52:54.359377 IP localhost.43101 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9855887], length 0

其實這就是我們配置的策略:

1 'tcp_keepinterval' => 1, // 1s探測一次
2 'tcp_keepcount' => 5, // 探測的次數,超過5次后還沒有回包close此連接

因為我們作業系統底層會自動的給客戶端回ack,所以這個連接不會在5次探測后被關閉,作業系統底層會持續不斷的發送這樣的一組包:

1 01:52:54.359341 IP localhost.6666 > localhost.43101: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9858736], length 0
2 01:52:54.359377 IP localhost.43101 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9855887], length 0

如果我們要測驗5次探測后關閉這個連接,可以禁掉6666埠的包:

1 ~/codeDir/phpCode/hyperf-skeleton # iptables -A INPUT -p tcp --dport 6666 -j DROP

這樣會把所有從6666埠進來的包給禁掉,自然,服務器就接收不到從客戶端那一邊發來的ack包了,

然后服務器過5秒就會列印出close(服務端主動的呼叫了close方法,給客戶端發送了FIN包):

1 ~/codeDir/phpCode/hyperf-skeleton # php server.php
2 string(17) "Client: Connect 1"
3 string(10) "close fd 1"

我們恢復一下iptables的規則:

1 ~/codeDir/phpCode # iptables -D INPUT -p tcp -m tcp --dport 6666 -j DROP

即把我們設定的規則給洗掉了,

通過tcp_keepalive的方式實作心跳的功能,優點是簡單,不要寫代碼就可以完成這個功能,并且發送的心跳包小,缺點是依賴于系統的網路環境,必須保證服務器和客戶端都實作了這樣的功能,需要客戶端配合發心跳包,還有一個更為嚴重的缺點是如果客戶端和服務器不是直連的,而是通過代理來進行連接的,例如socks5代理,它只會轉發應用層的包,不會轉發更為底層的tcp探測包,那這個心跳功能就失效了,

所以,Swoole就提供了其他的解決方案,一組檢測死連接的配置,

1 'heartbeat_check_interval' => 1, // 1s探測一次
2 'heartbeat_idle_time' => 5, // 5s未發送資料包就close此連接

swoole實作的heartbeat

我們來測驗一下:

 1 <?php
 2  
 3 $server = new \Swoole\Server('127.0.0.1', 6666, SWOOLE_PROCESS);
 4  
 5 $server->set([
 6 'worker_num' => 1,
 7 'heartbeat_check_interval' => 1, // 1s探測一次
 8 'heartbeat_idle_time' => 5, // 5s未發送資料包就close此連接
 9 ]);
10  
11 $server->on('connect', function ($server, $fd) {
12 var_dump("Client: Connect $fd");
13 });
14  
15 $server->on('receive', function ($server, $fd, $reactor_id, $data) {
16 var_dump($data);
17 });
18  
19 $server->on('close', function ($server, $fd) {
20 var_dump("close fd $fd");
21 });
22  
23 $server->start();

然后啟動服務器:

1 ~/codeDir/phpCode/hyperf-skeleton # php server.php

然后啟動tcpdump

 

1 ~/codeDir/phpCode # tcpdump -i lo port 6666
2 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
3 listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

 


然后再啟動客戶端:

1 ~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666

 


此時服務器端列印:

1 ~/codeDir/phpCode/hyperf-skeleton # php server.php
2 string(17) "Client: Connect 1"

 

然后tcpdump列印:

 

1 02:48:32.516093 IP localhost.42123 > localhost.6666: Flags [S], seq 1088388248, win 43690, options [mss 65495,sackOK,TS val 10193342 ecr 0,nop,wscale 7], length 0
2 02:48:32.516133 IP localhost.6666 > localhost.42123: Flags [S.], seq 80508236, ack 1088388249, win 43690, options [mss 65495,sackOK,TS val 10193342 ecr 10193342,nop,wscale 7], length 0
3 02:48:32.516156 IP localhost.42123 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 10193342 ecr 10193342], length 0

 

這是三次握手資訊,

然后過了5s后,tcpdump會列印出:

1 02:48:36.985027 IP localhost.6666 > localhost.42123: Flags [F.], seq 1, ack 1, win 342, options [nop,nop,TS val 10193789 ecr 10193342], length 0
2 02:48:36.992172 IP localhost.42123 > localhost.6666: Flags [.], ack 2, win 342, options [nop,nop,TS val 10193790 ecr 10193789], length 0

也就是服務端發送了FIN包,因為客戶端沒有發送資料,所以Swoole關閉了連接,

然后服務器端會列印:

1 ~/codeDir/phpCode/hyperf-skeleton # php server.php
2 string(17) "Client: Connect 1"
3 string(10) "close fd 1"

 

所以,heartbeat和tcp keepalive還是有一定的區別的,tcp keepalive有保活連接的功能,但是heartbeat存粹是檢測沒有資料的連接,然后關閉它,并且只可以在服務端這邊配置,如果需要保活,也可以讓客戶端配合發送心跳,

如果我們不想讓服務端close掉連接,那么就得在應用層里面不斷的發送資料包來進行保活,例如我在nc客戶端里面不斷的發送包:

 1 ~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666
 2 ping
 3 ping
 4 ping
 5 ping
 6 ping
 7 ping
 8 ping
 9 ping
10 ping

 

我發送了9個ping包給服務器,tcpdump的輸出如下:

 1 // 省略了三次握手的包
 2 02:57:53.697363 IP localhost.44195 > localhost.6666: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 10249525 ecr 10249307], length 5
 3 02:57:53.697390 IP localhost.6666 > localhost.44195: Flags [.], ack 6, win 342, options [nop,nop,TS val 10249525 ecr 10249525], length 0
 4 02:57:55.309532 IP localhost.44195 > localhost.6666: Flags [P.], seq 6:11, ack 1, win 342, options [nop,nop,TS val 10249686 ecr 10249525], length 5
 5 02:57:55.309576 IP localhost.6666 > localhost.44195: Flags [.], ack 11, win 342, options [nop,nop,TS val 10249686 ecr 10249686], length 0
 6 02:57:58.395206 IP localhost.44195 > localhost.6666: Flags [P.], seq 11:16, ack 1, win 342, options [nop,nop,TS val 10249994 ecr 10249686], length 5
 7 02:57:58.395239 IP localhost.6666 > localhost.44195: Flags [.], ack 16, win 342, options [nop,nop,TS val 10249994 ecr 10249994], length 0
 8 02:58:01.858094 IP localhost.44195 > localhost.6666: Flags [P.], seq 16:21, ack 1, win 342, options [nop,nop,TS val 10250341 ecr 10249994], length 5
 9 02:58:01.858126 IP localhost.6666 > localhost.44195: Flags [.], ack 21, win 342, options [nop,nop,TS val 10250341 ecr 10250341], length 0
10 02:58:04.132584 IP localhost.44195 > localhost.6666: Flags [P.], seq 21:26, ack 1, win 342, options [nop,nop,TS val 10250568 ecr 10250341], length 5
11 02:58:04.132609 IP localhost.6666 > localhost.44195: Flags [.], ack 26, win 342, options [nop,nop,TS val 10250568 ecr 10250568], length 0
12 02:58:05.895704 IP localhost.44195 > localhost.6666: Flags [P.], seq 26:31, ack 1, win 342, options [nop,nop,TS val 10250744 ecr 10250568], length 5
13 02:58:05.895728 IP localhost.6666 > localhost.44195: Flags [.], ack 31, win 342, options [nop,nop,TS val 10250744 ecr 10250744], length 0
14 02:58:07.150265 IP localhost.44195 > localhost.6666: Flags [P.], seq 31:36, ack 1, win 342, options [nop,nop,TS val 10250870 ecr 10250744], length 5
15 02:58:07.150288 IP localhost.6666 > localhost.44195: Flags [.], ack 36, win 342, options [nop,nop,TS val 10250870 ecr 10250870], length 0
16 02:58:08.349124 IP localhost.44195 > localhost.6666: Flags [P.], seq 36:41, ack 1, win 342, options [nop,nop,TS val 10250990 ecr 10250870], length 5
17 02:58:08.349156 IP localhost.6666 > localhost.44195: Flags [.], ack 41, win 342, options [nop,nop,TS val 10250990 ecr 10250990], length 0
18 02:58:09.906223 IP localhost.44195 > localhost.6666: Flags [P.], seq 41:46, ack 1, win 342, options [nop,nop,TS val 10251145 ecr 10250990], length 5
19 02:58:09.906247 IP localhost.6666 > localhost.44195: Flags [.], ack 46, win 342, options [nop,nop,TS val 10251145 ecr 10251145], length 0

 

有9組資料包的發送,(這里的Flags [P.]代表Push的含義)

此時服務器還沒有close掉連接,實作了客戶端保活連接的功能,然后我們停止發送ping,過了5秒后tcpdump就會輸出一組:

02:58:14.811761 IP localhost.6666 > localhost.44195: Flags [F.], seq 1, ack 46, win 342, options [nop,nop,TS val 10251636 ecr 10251145], length 0
02:58:14.816420 IP localhost.44195 > localhost.6666: Flags [.], ack 2, win 342, options [nop,nop,TS val 10251637 ecr 10251636], length 0
服務端那邊發送了FIN包,說明服務端close掉了連接,服務端的輸出如下:

 1 ~/codeDir/phpCode/hyperf-skeleton # php server.php
 2 string(17) "Client: Connect 1"
 3 string(5) "ping
 4 "
 5 string(5) "ping
 6 "
 7 string(5) "ping
 8 "
 9 string(5) "ping
10 "
11 string(5) "ping
12 "
13 string(5) "ping
14 "
15 string(5) "ping
16 "
17 string(5) "ping
18 "
19 string(5) "ping
20 "
21 string(10) "close fd 1"

 


然后我們在客戶端那邊ctrl + c來關閉連接:

 1 ~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666
 2 ping
 3 ping
 4 ping
 5 ping
 6 ping
 7 ping
 8 ping
 9 ping
10 ping
11 ^Cpunt!
12 
13 ~/codeDir/phpCode/hyperf-skeleton #

 

此時,tcpdump的輸出如下:

1 03:03:02.257667 IP localhost.44195 > localhost.6666: Flags [F.], seq 46, ack 2, win 342, options [nop,nop,TS val 10280414 ecr 10251636], length 0
2 03:03:02.257734 IP localhost.6666 > localhost.44195: Flags [R], seq 2678621620, win 0, length 0

 

應用層心跳

1、制定ping/pong協議(mysql等自帶ping協議)
2、客戶端靈活的發送ping心跳包
3、服務端OnRecive檢查可用性回復pong
例如:

 1 $server->on('receive', function (\Swoole\Server $server, $fd, $reactor_id, $data)
 2 {
 3 if ($data == 'ping')
 4 {
 5 checkDB();
 6 checkServiceA();
 7 checkRedis();
 8 $server->send('pong');
 9 }
10 });

 

結論
1、tcp的keepalive最簡單,但是有兼容性問題,不夠靈活
2、swoole提供的keepalive最實用,但是需要客戶端配合,復雜度適中
3、應用層的keepalive最靈活但是最麻煩

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/115594.html

標籤:PHP

上一篇:thinkphp5 + barcode 生成條形碼

下一篇:PHP+Swoole并發編程的魅力

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more