讀書筆記_python網路編程3_(1)

来源:https://www.cnblogs.com/wangxue533/archive/2019/11/26/11936665.html
-Advertisement-
Play Games

0.前言 代碼目錄: https://github.com/brandon rhodes/fopnp/tree/m/py3 0.1.網路實驗環境:理解客戶端與伺服器是如何通過網路進行通信的 每台機器通過一個Docker容器實現 0.1.1.數據機A和B下麵的客戶機(h1~h4)表示典型客戶端場景 ...


0.前言

代碼目錄: https://github.com/brandon-rhodes/fopnp/tree/m/py3

0.1.網路實驗環境:理解客戶端與伺服器是如何通過網路進行通信的


每台機器通過一個Docker容器實現

0.1.1.數據機A和B下麵的客戶機(h1~h4)表示典型客戶端場景,家庭或咖啡店(內部網路,不能訪問互聯網,如果要連互聯網,都通過數據機IP進行連接)

0.1.2.數據機通過ISP網關連接廣域網(主幹路由器,負責將數據包發送至與之相連的網路)

0.1.3.example.com及相連機器表示機房配置。沒有網路地址轉換或偽裝,互聯網上的各個客戶端可隨意訪問example.com後的三個伺服器提供的服務埠

0.1.4.ftp、mail、www伺服器運行正確配置的守護進程,Python腳本可以運行在其他機器,併成功連接到上述服務

0.1.5.所有伺服器成功安裝TLS證書,所有客戶機有example.com的簽名及安裝受信證書,及要求TLS認證的Python腳本可以成功獲取認證

0.1.6.可以在網路環境的任意一臺機器上連接並運行命令,可對網路中的任意一個點進行數據包追蹤,查看客戶端和服務端之間的網路數據傳輸情況

1.客戶端、伺服器網路編程

1.1.協議棧與庫

1.1.1.協議棧:複雜的網路服務建立在簡單網路服務的基礎上

1.1.2.使用Python庫(內置標準庫+三方庫),解析要使用的網路通信協議

網路編程就是選擇並使用一個已經支持所需網路操作的庫的過程。通過瞭解底層網路服務知識,除了可以理解網路庫的運行原理,還能夠在底層部分出現錯誤時,知道具體發生了什麼。

標準庫:http://docs.python.org/3/library/

三方庫:https://pypi.python.org/

谷歌地理編碼服務pygeocoder包

郵箱地址:207 N. Defiance St Archbold, OH
獲取該物理地址的緯度和經度:      

安裝virtualenv來避免,在幾個月的開發後,Python安裝環境包含無用包及新安裝包與已安裝包不相容的問題。

win中,虛擬環境中包含Python二進位文件的目錄為Scripts,不是bin

virtualenv -p python3 geo_env
cd geo_env
ls
O]bin/ include/ lib/
.bin/activate
python -c 'import pygeocoder'
O]error

pygcocoder包未安裝,在虛擬環境中使用pip安裝pygeocoder包

pip install pygeocoder
python -c 'import pygeocoder'
#獲取經度與緯度 search1.py
#!/usr/bin/env python3
from pygeocoder import Geocoder

if __name__ == "__main__":
    address = '207 N. Definace St, Archbold, OH'
    print(Geocoder.geocode(address)[o].coordinates)

執行python3 search1.py
O](41.521954, -84.306691)
pygeocoder介面背後的原理是怎樣的?
後面將詳細學習如何在一個包含至少6層的網路協議棧的頂層構建這個複雜的服務

1.2.應用層:

如果需要自己為谷歌地圖API編寫客戶端:沒有使用直接提供地理編功能的三方庫,而是使用更底層的Requests庫。

#!/usr/bin/env python3
#/chapter01/search2.py
import requests

def geocode(address):
    parameters = {'address': address, 'sensor': 'false'}
    base = 'http://maps.googleapis.com/maps/api/geocode/json'
    response = requests.get(base, params=parameters)
    answer = response.json()
    print(answer['results'][0]['geometry']['location']

if __name__ == '__main__':
    gecode('207 N. Definace St, Archbold, OH')

執行python3 search2.py
O]{'lat': 41.521954, 'lng': -84.306691}
結果並不完全相同,JSON數據將結果封裝為對象,Requests庫以Python字典形式提供該對象

谷歌文檔:http://code.google.com/apis/maps/documentation/geocodeing/

search2.py沒有通過地址和緯度直接解決問題,而是通過構造URL,獲取查詢響應,然後將結果轉化為JSON,一步步解決問題

高層的代碼描述了查詢的意義,而底層的代碼展示了查詢的構造細節

1.3.協議的使用:

search2.py腳本構建了一個URL,並獲取了該URL查詢的響應文檔,為了使URL查詢看起來像一個基礎操作,Web瀏覽器做了很多事情。
URL可以獲取某個文檔的原因:描述了網路上該特定文檔的位置及獲取方法。提供了更底層協議查詢該文檔所需的指令,search2.py就能夠解析URL並獲取響應文檔了。
URL包含了協議的名稱,後面跟著保存文檔的主機名,最後是該主機上特定文檔的路徑。
Requests庫從谷歌獲取結果的具體原理,其實就是由HTTP提供的,如果不想使用Requests庫提供的功能,而是想直接使用HTTP來獲取結果,使用/chapter01/search3.py

#!/usr/bin/env python3

import http.client
import json
from urllib.parse import quote_plus

base = '/maps/api/geocode/json'

def geocode(address):
    path = '{}?address={}&sensor=false'.format(base, quote_polus(address))
    connection = http.client.HTTPConnection('maps.google.com')
    connection.request('GET', path)
    rawreply = connection.getresponse().read()
    reply = json.loads(rawreply.decode('utf-8'))
    print(reply['results'][o]['geometry']['location'])

if __name__ == '__main__':
    geocode('207 N. Definace St, Archbold, OH')

該程式直接使用HTTP協議:請求連接特定主機->手動構造帶path參數的GET查詢->直接從HTTP連接獲取響應結果。
此方法沒有使用字典將查詢參數方便的表示為獨立的鍵值對,而是手動嵌入到查詢地址中。
要通過該方法完成查詢,需要在?後跟上&分隔的參數,這些參數通過name=value的形式表示

1.4.原始的網路會話

HTTP協議利用,現代操作系統提供的使用TCP協議在IP網路的不同程式間進行純文本網路會話的功能,在兩台機器間傳輸數據。
HTTP協議精確描述了兩台主機間通過TCP傳輸的信息格式,並以此提供HTTP的各項功能。
通過Python可以方便操作的網路協議棧的最底層:/chapter01/search4.py,像網路發送了一個原始文本信息作為請求,並收到了很多原始文本作為響應。

#!/usr/bin/env python3
import socket
from urllib.parse import quote_plus

request_text = """\
GET /maps/api/geocode/json?address={}&sensor=false HTTP/.1\r/n/
Host: maps.google.com:80\r\n\
User-Agent:search4.py (Foundations of Python Network Programming)\r\n\
Connection: close\r\n\
\r\n\
"""
def geocode(address):
    sock = socket.socket()
    sock.connect(('maps.google.com', 80))
    request = request_text.format(quote_plus(address))
    sock.sendall(request.encode('ascii'))
    raw_reply = b''
    while True:
        more = sock.recv(4096)
        if not more:
            break
        raw_reply += more
    print(raw_reply.decode('utf-8'))

if __name__ == '__main__':
    geocode('207 N. Defiance St, Archbold, OH')

search4.py本質的不同:深入到最底層:使用主機操作系統提供的原始socket()函數來支持IP網路上的網路通信。相當於C寫底層系統一樣
原始網路通信的過程就是發送與接收字元串的過程。發送的查詢是一個字元串,接收到的響應同樣也是一個字元串。
通過sendall()函數傳入的參數瞭解到該HTTP查詢的具體內容。查詢中包含了關鍵字GET,GET後跟著待獲取文檔的路徑以及支持的HTTP版本。
GET /maps/api/geocode/json?address=207+N.+Defiance+St%2C+Archbold%2C+OH&sensor=false HTTP/1.1
GET信息後跟著一些請求頭,每個請求頭包含了名稱、冒號、值。最後是請求結束的回車符和換行符
python search4.py

O]
HTTP/1.1 200 OK
Content-Type:
Date: Sat, 23 Nov 2013 18:34:30 GMT
Expires: Sun, 24 Nov 2013 18:34:30 GMT
Cache-Control:public, max-age=86500
Vary: Accept-Language
Access-Control_Allow-Origin: *
Server: mafe
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Alternate-Protocol: 80:quic
Connection: close
{
    "results": [
        {
            ...
            "formatted_address": "207 North Definace Street, Archbold, OH 43502, USA",
            "geometry": {
                "location" : {
                    "lat" : 41.521954,
                    "lng" : -84.306691
                },
                ...
            },
            "types" : [ "street_address" ]
        }
    ],
    "status": "OK"
}

HTTP響應的結構和HTTP請求類似。首先是狀態行,跟著一些響應頭,響應頭後有一個空行,接著就是響應體(JSON格式~JavaScripts數據結構),此JSON就是之前查詢的響應結果,描述了查詢谷歌地理編碼API返回的地理位置。
這裡所有狀態和響應頭都是使用httplib庫處理的底層細節。如果沒有沒有分層,網路通信的具體細節即為此。

1.5.層層深入

1.5.1.協議棧:先構建利用網路硬體在兩台PC間傳送文本字元串的原始會話功能,然後在此基礎上創建更複雜、更高層語義更豐富的對話(郵寄地址對應的地理位置)。

例子中分析的協議棧包含4層

谷歌地理編碼API,封裝了1)如何用URL表示地理信息查詢;2)如何獲取包含坐標信息的JSON數據
URL,標識了科通過HTTP獲取的文檔
HTTP層,支持面向文檔的命令(GET),操作使用了原始TCP/IP套接字
TCP/IP套接字,只處理位元組串的發送和接收

1.5.1.1.協議棧的每一層都使用了其底層協議提供的功能,並同時向上層協議提供服務。

1.5.1.2.Python對涉及的各網路層都提供了非常全面的支持。除非使用應用提供商定製的協議並定製請求的格式(pygeocoder連接谷歌服務),否則無需使用三方庫

1.5.1.3.使用的通信協議越底層,程式質量也明顯隨之下降。故應該儘可能使用標準庫或三方庫。

1.5.1.4.高層的網路協議(如解析街道地址的谷歌地理編碼API)通常會將底層網路細節隱藏,如果值使用過pygeocoder庫,可能永遠不會知道URL和HTTP是pygeocoder用來解決問題的底層機制。

1.5.1.5.socket()介面其實並不是查詢谷歌涉及的最底層的協議,套接字這一抽象其實也基於更底層的協議,只不過這些協議由操作系統管理,非Python

socket()API層以下的幾層:

1.5.2.1.傳輸控制協議(TCP),通過發送、接收以及重排數據包(packet)的小型網路星系,支持由位元組流組成的雙向網路會話。

1.5.2.2.網際協議(IP),該層處理不同電腦間數據包的發送

1.5.2.3.最底層的"鏈路層",負責在直接相連的電腦之間發送物理星系,由網路硬體設備組成,如乙太網埠和無線網卡

1.6.編碼與解碼

1.6.1.python3對字元串和底層位元組序列做了區分。

1.6.1.1.位元組(byte)是網路通信中實際傳輸的二進位數。每個位元組8位二進位,範圍從00000000到11111111,轉為十進位就是0到255.

1.6.1.2.字元(character)串包含了Unicode字元,如a、{,∅(空集)。每個Unicode字元均有一個編碼點(code point)的數字標識符與之對應。除非主動請求Python對字元和外部可見的實際位元組進行相互轉化,否則對使用者可見的只有字元。

1.6.2.位元組和字元串兩者間的相互操作為解碼(decoding)和編碼(encoding)

1.6.2.1.解碼:應用程式使用位元組時發生的。當應用程式從文件或網路接收到位元組時,程式就像一個一流間諜一樣,對通信通道間傳輸的原始位元組進行解密。

1.6.2.2.編碼:程式將字元串對外輸出時所實施的過程。此時應用程式使用一種編碼方法將字元串轉化為位元組。當電腦需要傳輸或存儲符號時,位元組才是真正使用的格式。

使用python3操作這兩個過程相當簡單。

1.6.3.1.使用decode()方法將讀入的位元組串轉化為字元串,

1.6.3.2.使用encode()方法對要輸出的字元串進行編碼。

if __name__ == '__main__':
    # Translating from the outside world of bytes to Unicode characters.
    input_bytes = b'\xff\xfe4\x001\x003\x00 \x00i\x00s\x00 \x00i\x00.\x00'
    input_characters = input_bytes.decode('utf-16')
    print(repr(input_characters))

    # Translating chsracters back into bytes before sending them.
    output_characters = 'We copy you down, Eagle.\n'
    output_bytes = output_characters.encode('utf-8')
    with open ('eagle.txt', 'wb') as f:
        f.write(output_bytes)

註意在調用兩者的repr()方法時的區別:

1.6.4.1.位元組串由字母b開始,如b'Hello';

1.6.4.2.字元串則沒有起始字母,如'world'。

為了消除位元組串與字元串帶來的混淆,Py3只對字元串類型提供了大量的字元串方法。

1.7.網際協議(IP):為全世界通過互聯網連接的電腦賦予統一地址系統的一種機制,使得數據包能夠從互聯網的一段發送至另一段。理想情況下。網路瀏覽器無需瞭解具體使用哪種網路設備來傳輸數據包,就能夠連接上任意一臺主機。

1.7.1.網路互聯是通過物理鏈路將多台電腦連接,使之可以互相通信。

1.7.2.網際互聯是將相鄰的物理網路相連,使之形成更大的網路系統,如互聯網。

但兩者本質都是允許資源共用的精心設計的機制。

1.7.3.電腦中的各種各樣的資源都需要被共用,網路設備間進行共用的基本單元是數據包(packet),只要有需要,就可以交換。一個數據表是一串長度在幾位元組到幾千位元組間的位元組串,是網路設備間進行數據傳輸的基本單元。

1.7.4.數據包在物理層通常只有兩個屬性:包含的位元組串數據+目標傳輸地址。

1.7.5.物理數據包的地址一般是一個唯一的標識符,表示了再傳輸數據包的過程中,插入同一乙太網段的其他網卡或無線通道。

1.7.6.網卡負責發送並接收這樣的數據包,使得電腦操作系統不用關心網路是如何處理網線、電壓即信號這些細節的。

Python程式很少直接操作IP這麼底層的協議。

1.8.IP地址:最初版本為連接到萬維網的每台電腦分配了一個4位元組的地址,通常寫為由句點分隔的十進位數。每個十進位數表示地址的1位元組,因此,每個數的範圍是0到255。

由於純數字表示的地址不便記憶,人們使用主機名(hostname)來代替IP地址,只要鍵入google.com就可訪問谷歌,其實,它是將主機名解析到了類似74.125.67.103的地址,實際上通過互聯網將數據包傳輸到了該地址。

# 1-7 chapter01/getname.py 主機名轉換為IP地址
import socket

if __name__ == '__main__':
    hostname = 'www.python.org'
    addr = socket.gethostbyname(hostname)
    print('The IP address of {} is {}'.format(hostname, addr))
O]The IP address of www.python.org is 151.101.40.223

1.8.1.無論一個互聯網應用程式看起來多麼新奇,實際上IP協議總是使用數字表示的IP地址來作為數據包傳輸的目標地址。

1.8.2.將主機名解析為IP地址這一複雜的細節是由操作系統來處理的,操作系統傾向於自己處理IP的多數操作細節,對於用戶及Python代碼不可見。

4位元組IP已經不夠用,又部署了IPv6的拓展地址機制,允許使用16位元組的地址:fe80::fcfd:4aff:fecf:ea4e,只要代碼從用戶處接收IP地址或主機名,將它們傳遞給網路庫來處理,那麼就永遠不需要考慮IPv4和v6的區別,運行代碼的操作系統會知道使用的IP版本,並作出相應的解析。

1.8.2.IP地址從左往右,前兩個直接表示某個機構,第3個位元組表示目標機器所在的特定子網,最後一個位元組將地址細化至該特定的機器或服務。

1.8.3.特殊IP地址段:

1.8.3.1.127...*:由機器上運行的本地應用程式使用。當程式連接到這一地址段中的地址時,其實是在與同一機器上的一些其他服務或程式交互。大多數只使用127.0.0.1,表示該程式的機器本身,通常可以通過主機名localhost來訪問

1.8.3.2.10...、172.16-31..、192.168..*:為私有子網(private subnet)預留的。
運營互聯網的機構保證,絕不會把這三個地址段中的任何地址分發給運行伺服器或服務的實體公司。故連接互聯網時,這些地址是沒有意義的,並不對應可連接的任一主機。
構建組織內部網路,可以隨意使用這些地址來自由分配內部的IP地址,不需讓外網訪問這些主機。

1.9.路由:根據目的IP地址,選擇將IP數據包發往何處

一旦程式請求操作系統向某一特定IP地址發送數據,操作系統就需要決定如何使用該機器連接的某一物理網路來傳輸數據。這一決定就叫路由(routing)

1.9.1. 如果IP地址形如127...*,那麼操作系統會知道數據包的目的地址,是本機運行的另一個程式,該數據包不會傳送給物理網路設備,直接通過操作系統內部數據複製轉交給另一應用程式。

1.9.2. 如果目的IP地址與本機處於同一子網,可以通過簡單檢查本地乙太網段、無線通道,或是其他任何網路信息來找到目標主機,將數據包發送給本地連接的機器。

1.9.3. 否則將數據包轉發給一臺網關機器(gateway machine),該網關將本地子網連接至互聯網,再決定將該數據包發往何處。

路由只是在網路邊緣時才這麼容易,Py應用程式很少運行在互聯網骨幹路由器上,所以實際情況幾乎全是簡單路由情形。

1.9.4. 同一子網中所有主機有著相同的IP地址首碼,信號表示地址可變部分,但ASCII信號並沒有插入到路由表中,而是通過結合IP地址和掩碼來表示子網。

1.9.5. 掩碼指出了某主機屬於某子網所需的高位比特匹配數。

1.9.5.1. 127.0.0.0/8:該模式指出地址的前8位(1位元組必須與127匹配,餘下的24位(3位元組)則可以是任意值。

1.9.5.2. 192.168.0.0/16:該模式匹配了屬於192.168私有地址段的任何IP地址,指出前16位必須完全匹配,後16位可以是任意值

1.9.5.3. 192.168.5.0/24:明確指定一個特定的獨立子網,最常見的子網掩碼。屬於該子網的機器只有最後1位元組不同,允許有256個不同的地址。通常, .0地址用來表示子網名, .255地址用作'廣播數據包'的目標地址,會被髮送到子網內的所有主機。這樣,就有254個地址隨機分配給電腦。 .1地址通常用於連接外網的網關,但有些公司/學校也會選擇其他地址。

py代碼直接使用主機操作系統體統的功能,去正確選擇數據包路由,和之前依靠操作系統來將主機名解析至IP地址是一樣的。

1.10.數據包分組

IP支持的數據包極大,最大可至64KB,但是構建於IP網路之上的實際網路設備,通常並不支持這麼大的數據包,所以分組是必要的。乙太網只支持1500B的數據包。
網路數據包中包含一個表示"不分組"(DF,Don't Fragment)的標記,在源電腦與目的電腦之間的某條物理網路無法容納太大的數據包時,發送者可以通過這個標記選擇是否進行分組。

1.10.1.如果沒有設置DF標記,允許分組。當數據包大小超過網路能夠容納的上限時,網關能夠將其分為多個小數據包,併進行標記,表示接受方在接受之後需要將這些小數據包重組為原始大數據包。-->將大的拆分為小的,接收後再拼接成大的。

1.10.2.如果設置了DF標記,不允許分組。如果網路無法容納數據包,將會丟棄該數據包,併發回一條錯誤信息。錯誤信息由特殊信號數據包表示,叫做Internet控制報文協議(ICMP)數據包。發送方在收到錯誤後,會嘗試將信息分割為較小的數據包重發

DF標記無法由Py程式控制,由操作系統來設置。-->一開始就一直發小的,接收小的
系統通常使用的邏輯:

1.10.3.如果正在進行一個,由網路鍵傳輸的獨立數據報組成的UDP會話,那麼操作系統不會設置DF標記,故無論需要傳輸多少數據,所有數據包都能到達接收方。

1.10.4.如果是TCP會話,TCP可能是由多達上千個數據包組成的長數據流,那麼系統將設置DF標記,選擇正確的數據包大小,使得TCP會話順暢進行,如果不這樣做,數據包會在途中不斷分組,從而使得會話較為低效。

一個互聯網子網能夠接收的最大數據包叫做最大傳輸單元(MTU),90年代,互聯網服務商(DSL鏈路電話公司)使用PPPoE,PPPoE對IP數據包進行封裝,封裝後大小隻有1492B,不是乙太網允許的1500B,使得很多預設1500B的網站措手不及,還使用錯誤的安全措施,阻塞了所有的ICMP數據包,收不到錯誤信息,就不知道1500B的數據包到達客戶的DSL鏈路時無法相容,導致小文件和網頁的訪問沒有問題,Telnet和SSH等互動式協議也都正常,這兩種操作發送的數據包都小於1492B。一旦用戶嘗試下載一個大文件,或者Telnet/SSH一次性大量輸出好幾個屏幕的信息,那麼連接就會被凍結並無法響應。

1.11.進一步學習IP

餘下的章節,學習IP層之上的協議,描述IP的官方資源是IETF發佈的RFC文檔,可以瞭解到網際協議工作的每個細節,網址:http://tools.ietf.org/html/rfc791

或《TCP/IP詳解:協議》

1.12.小結

1.12.1.協議棧

1.12.2.TCP/IP協議,僅支持在客戶端和服務端之間傳輸位元組串

1.12.3.HTTP協議,描述客戶端如何通過TCP/IP建立的鏈接來請求特定的文檔,以及伺服器如何響應並提供相應的結果。

1.12.4.萬維網將獲取由HTTP托管的文檔所需的指令,編碼為一個特殊的地址,這個地址稱為URL。

1.12.5.在伺服器需要向客戶端返回結構化數據時,標準JSON數據格式是最流行的表示返迴文檔的個數。

1.12.6.在整個複雜的體系之上,谷歌提供了一個地理編碼服務,程式員可以構建一個URL用戶請求,而谷歌會返回一個描述地理位置的JSON文檔

1.12.7.當需要在網路上傳輸文本信息,或以位元組的方式存儲到設備上時,都要將字元編碼為位元組。最常用的將字元表示為位元組的方法是簡單而又有效的ASCII編碼,以及強大而又通用Unicode系統。UTF-8是尤為常見的Unicode編碼方法。

1.12.8.可用PY的decode()將位元組串->字元串,encode()將字元串->位元組串,Py3永遠不會自動將直接轉換為字元串,必須事先知道所使用的編碼方法,故相比於Py2,需要更多地調用decode()和encode()。

1.12.9.IP網路幫助應用程式傳輸數據包,網路管理員、設備供應商、操作系統程式員協力為單獨的機器分配了IP地址,在機器及路由器上建立了路由表,並配置了功能變數名稱系統,以將IP地址和用戶可見的功能變數名稱關聯起來。每個IP數據包再發往目的地址時,都有自己的傳輸路徑。

1.12.10.如果一個數據包超過了傳輸路徑上,路由器鍵一跳的大小限制,可能會對這個數據包進行分組。

1.12.11.大多數應用程式中,兩種使用IP的基本方法。

1.12.11.1.第一種,將每個數據包視為獨立的信息來使用->UDP

1.12.11.2.第二種,請求一個被自動分為多個數據包的數據流->TCP


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 練習1:求兩個數字的和:獲取任意的兩個數字的和 function getSum(x, y) { return x + y; } console.log(getSum(10, 20)); 練習2:求1-100之間所有的數字的和 function geteverySum() { var sum = 0; ...
  • 前言 最近在做 webapp,遇到了很多移動端相容的問題,其中一個問題就是:輸入框觸發 focus 後,鍵盤彈出,然後遮住了輸入框。 然後在 和`IOS`上,這個問題的表現形式不一樣,而原生鍵盤和第三方鍵盤也不一樣,但引起的問題都是一樣的:輸入框被遮住了。 需要的效果 在鍵盤彈出時,獲得焦點的輸入框 ...
  • 首先,我們來看下垂直居中: (1)、如果是單行文本,則可以設置的line-height的數值,讓其等於父級元素的高度! <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" conte ...
  • 關於call和apply,以前也思考良久,很多時候都以為記住了,但是,我太難了。今天我特地寫下筆記,希望可以完全掌握這個東西,也希望可以幫助到任何想對學習這個東西的同學。 一.apply函數定義與理解,先從apply函數出發 在MDN上,apply的定義是: “apply()方法調用一個具有給定th ...
  • 下麵代碼中,setTimeout(fn, 0)在下一輪“事件迴圈”開始時執行,Promise.resolve()在本輪“事件迴圈”結束時執行,console.log('one')則是立即執行,因此最先輸出。 下麵代碼中,setTimeout(fn, 0)在下一輪“事件迴圈”開始時執行,Promise ...
  • 慕課網 實戰班 就業班 2019年11月26號 更新資料整理 300套 只讀模式打開 百度網盤資料鏈接: 鏈接:https://pan.baidu.com/s/1oCq9pOhVYnbg1N0MJQp6Iw提取碼:wsds複製這段內容後打開百度網盤手機App,操作更方便哦 微雲鏈接: https:/ ...
  • 為什麼寫這篇文章 自己以前都走了彎路,以為學習戰術設計就會DDD了,其實DDD的精華在戰略設計,但是對於我們菜鳥來說,學習一些技術概念也是挺好的 經常看到這些術語,概念太多,也想簡單學習一下,記憶力比較差記錄一下實現的細節 領域事件 1.領域事件是過去發生的與業務有關的事實,一但發生就不可更改,所以 ...
  • 爬取51Job和獵聘網的信息,想處理字元集問題(51job為gbk,獵聘為utf-8), 找到兩個網站字元集信息都在同一標簽下 就想先把網頁保存成String,解析一遍獲取字元集,然後將網頁轉換成對應的正確的字元集,最後再轉換成統一的字元集utf-8 1.0實現,2次調用Entity.Utils.t ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...