數據協議
⑴ 封裝UDP報文的IP數據包首部協議欄位值為____,封裝TCP報文的IP數據包首部協議欄位值為___
上圖是IP包的頭結構,其中協議(Protocol)部分長度8比特。標識了上層所使用的協版議。
以下是權比較常用的協議號:
1ICMP
2IGMP
6TCP
17 UDP
88 IGRP
89 OSPF
所以,封裝了UDP包,值 為17,封裝了TCP包,值 為6.
⑵ 為什麼數據中要有協議
沒有通信協議,我們都用自己的協議,那介面不就是不同的了嗎?那樣就沒有辦法通信了.
⑶ 什麼是「數據帶通用協議」
數據傳輸通用協議包括:TCP/IP協議、IPX/SPX協議、NetBEUI協議等。(專用通信協議相對於通用數據協議而言,如:VPN等)利用這些協議「附帶」傳輸數據非常危險,很容易被截獲。普通的抓包軟體就可以將這些數據包內容解析出來,獲得「附帶」的數據。
利用通用協議傳輸數據被稱為「隱蔽通道」。這種數據傳輸方式被拒絕,原因主要有兩個:
一是利用這種方式傳遞合法數據是危險的,因此很少有人使用;
二是非法分子利用這種傳遞方式傳遞惡意代碼,可能對系統造成很大損害。這是四級安全防護要求避免這種數據傳輸方式的主要目的。
⑷ 數據協議標准 的定義
PDU
傳輸層的數據叫段
網路層叫包
數據鏈路層叫幀
物理層叫比特流
⑸ 單片機中所說的通信協議是什麼
單片機通信協議
現在大部分的儀器設備都要求能過通過上位機軟體來操作,這樣方便調試,利於操作。其中就涉及到通信的過程。在實際製作的幾個設備中,筆者總結出了通信程序的通用寫法,包括上位機端和下位機端等。
1.自定義數據通信協議
這里所說的數據協議是建立在物理層之上的通信數據包格式。所謂通信的物理層就是指我們通常所用到的RS232、RS485、紅外、光纖、無線等等通信方式。在這個層面上,底層軟體提供兩個基本的操作函數:發送一個位元組數據、接收一個位元組數據。所有的數據協議全部建立在這兩個操作方法之上。
通信中的數據往往以數據包的形式進行傳送的,我們把這樣的一個數據包稱作為一幀數據。類似於網路通信中的TCPIP協議一般,比較可靠的通信協議往往包含有以下幾個組成部分:幀頭、地址信息、數據類型、數據長度、數據塊、校驗碼、幀尾。
幀頭和幀尾用於數據包完整性的判別,通常選擇一定長度的固定位元組組成,要求是在整個數據鏈中判別數據包的誤碼率越低越好。減小固定位元組數據的匹配機會,也就是說使幀頭和幀尾的特徵位元組在整個數據鏈中能夠匹配的機會最小。通常有兩種做法,一、減小特徵位元組的匹配幾率。二、增加特徵位元組的長度。通常選取第一種方法的情況是整個數據鏈路中的數據不具有隨即性,數據可預測,可以通過人為選擇幀頭和幀尾的特徵字來避開,從而減小特徵位元組的匹配幾率。使用第二種方法的情況更加通用,適合於數據隨即的場合。通過增加特徵位元組的長度減小匹配幾率,雖然不能夠完全的避免匹配的情況,但可以使匹配幾率大大減小,如果碰到匹配的情況也可以由校驗碼來進行檢測,因此這種情況在絕大多說情況下比較可靠。
地址信息主要用於多機通信中,通過地址信息的不同來識別不同的通信終端。在一對多的通信系統中,可以只包含目的地址信息。同時包含源地址和目的地址則適用於多對多的通信系統。
數據類型、數據長度和數據塊是主要的數據部分。數據類型可以標識後面緊接著的是命令還是數據。數據長度用於指示有效數據的個數。
校驗碼則用來檢驗數據的完整性和正確性。通常對數據類型、數據長度和數據塊三個部分進行相關的運算得到。最簡單的做法可是對數據段作累加和,復雜的也可以對數據進行CRC運算等等,可以根據運算速度、容錯度等要求來選取。
2.上位機和下位機中的數據發送
物理通信層中提供了兩個基本的操作函數,發送一個位元組數據則為數據發送的基礎。數據包的發送即把數據包中的左右位元組按照順序一個一個的發送數據而已。當然發送的方法也有不同。
在單片機系統中,比較常用的方法是直接調用串口發送單個位元組數據的函數。這種方法的缺點是需要處理器在發送過程中全程參與,優點是所要發送的數據能夠立即的出現在通信線路上,能夠立即被接收端接收到。另外一種方法是採用中斷發送的方式,所有需要發送的數據被送入一個緩沖區,利用發送中斷將緩沖區中的數據發送出去。這種方法的優點是佔用處理器資源小,但是可能出現需要發送的數據不能立即被發送的情況,不過這種時延相當的小。對於51系列單片機,比較傾向於採用直接發送的方式,採用中斷發送的方式比較佔用RAM資源,而且對比直接發送來說也沒有太多的優點。以下是51系列單片機中發送單個位元組的函數。
void SendByte(unsigned char ch)
{
SBUF = ch;
while(TI == 0);
TI = 0;
}
上位機中關於串口通信的方式也有多種,這種方式不是指數據有沒有緩沖的問題,而是操作串口的方式不同,因為PC上數據發送基本上都會被緩沖後再發送。對於編程來說操作串口有三種方式,一、使用windows系統中自帶的串口通信控制項,這種方式使用起來比較簡單,需要注意的是接收時的阻塞處理和線程機制。二、使用系統的API直接進行串口數據的讀取,在windows和linux系統中,設備被虛擬為文件,只需要利用系統提供的API函數即可進行串口數據的發送和讀取。三、使用串口類進行串口操作。在此只介紹windows環境下利用串口類編程的方式。
CSerialPort是比較好用的串口類。它提供如下的串口操作方法:
void WriteToPort(char* string, int len);
串口初始化成功後,調用此函數即可向串口發送數據。為了避免串口緩沖所帶來的延時,可以開啟串口的沖刷機制。
3.下位機中的數據接收和協議解析
下位機接收數據也有兩種方式,一、等待接收,處理器一直查詢串口狀態,來判斷是否接收到數據。二、中斷接收。兩種方法的優缺點在此前的一篇關於串口通信的文章中詳細討論過。得出的結論是採用中斷接收的方法比較好。
數據包的解析過程可以設置到不同的位置。如果協議比較簡單,整個系統只是處理一些簡單的命令,那麼可以直接把數據包的解析過程放入到中斷處理函數中,當收到正確的數據包的時候,置位相應的標志,在主程序中再對命令進行處理。如果協議稍微復雜,比較好的方式是將接收的數據存放於緩沖區中,主程序讀取數據後進行解析。也有兩種方式交叉使用的,比如一對多的系統中,首先在接收中斷中解析「連接」命令,連接命令接收到後主程序進入設置狀態,採用查詢的方式來解析其餘的協議。
以下給出具體的實例。在這個系統中,串口的命令非常簡單。所有的協議全部在串口中斷中進行。數據包的格式如下:
0x55, 0xAA, 0x7E, 0x12, 0xF0, 0x02, 0x23, 0x45, SUM, XOR, 0x0D
其中0x55, 0xAA, 0x7E為數據幀的幀頭,0x0D為幀尾,0x12為設備的目的地址,0xF0為源地址,0x02為數據長度,後面接著兩個數據0x23, 0x45,從目的地址開始結算累加、異或校驗和,到數據的最後一位結束。
協議解析的目的,首先判斷數據包的完整性,正確性,然後提取數據類型,數據等數據,存放起來用於主程序處理。代碼如下:
if(state_machine == 0) // 協議解析狀態機
{
if(rcvdat == 0x55) // 接收到幀頭第一個數據
state_machine = 1;
else
state_machine = 0; // 狀態機復位
}
else if(state_machine == 1)
{
if(rcvdat == 0xAA) // 接收到幀頭第二個數據
state_machine = 2;
else
state_machine = 0; // 狀態機復位
}
else if(state_machine == 2)
{
if(rcvdat == 0x7E) // 接收到幀頭第三個數據
state_machine = 3;
else
state_machine = 0; // 狀態機復位
}
else if(state_machine == 3)
{
sumchkm = rcvdat; // 開始計算累加、異或校驗和
xorchkm = rcvdat;
if(rcvdat == m_SrcAdr) // 判斷目的地址是否正確
state_machine = 4;
else
state_machine = 0;
}
else if(state_machine == 4)
{
sumchkm += rcvdat;
xorchkm ^= rcvdat;
if(rcvdat == m_DstAdr) // 判斷源地址是否正確
state_machine = 5;
else
state_machine = 0;
}
else if(state_machine == 5)
{
lencnt = 0; // 接收數據計數器
rcvcount = rcvdat; // 接收數據長度
sumchkm += rcvdat;
xorchkm ^= rcvdat;
state_machine = 6;
}
else if(state _machine == 6 || state _machine == 7)
{
m_ucData[lencnt++] = rcvdat; // 數據保存
sumchkm += rcvdat;
xorchkm ^= rcvdat;
if(lencnt == rcvcount) // 判斷數據是否接收完畢
state_machine = 8;
else
state_machine = 7;
}
else if(state_machine == 8)
{
if(sumchkm == rcvdat) // 判斷累加和是否相等
state_machine = 9;
else
state_machine = 0;
}
else if(state_machine == 9)
{
if(xorchkm == rcvdat) // 判斷異或校驗和是否相等
state_machine = 10;
else
state_machine = 0;
}
else if(state_machine == 10)
{
if(0x0D == rcvdat) // 判斷是否接收到幀尾結束符
{
retval = 0xaa; // 置標志,表示一個數據包接收到
}
state_machine = 0; // 復位狀態機
}
此過程中,使用了一個變數state_machine作為協議狀態機的轉換狀態,用於確定當前位元組處於一幀數據中的那個部位,同時在接收過程中自動對接收數據進行校驗和處理,在數據包接收完的同時也進行了校驗的比較。因此當幀尾結束符接收到的時候,則表示一幀數據已經接收完畢,並且通過了校驗,關鍵數據也保存到了緩沖去中。主程序即可通過retval的標志位來進行協議的解析處理。
接收過程中,只要哪一步收到的數據不是預期值,則直接將狀態機復位,用於下一幀數據的判斷,因此系統出現狀態死鎖的情況非常少,系統比較穩定,如果出現丟失數據包的情況也可由上位機進行命令的補發,不過這種情況筆者還沒有碰到。
對於主程序中進行協議處理的過程與此類似,主程序循環中不斷的讀取串口緩沖區的數據,此數據即參與到主循環中的協議處理過程中,代碼與上面所述完全一樣。
4.上位機中的數據接收和命令處理
上位機中數據接收的過程與下位機可以做到完全一致,不過針對不同的串口操作方法有所不同。對於阻賽式的串口讀函數,例如直接進行API操作或者調用windows的串口通信控制項,最好能夠開啟一個線程專門用於監視串口的數據接收,每接收到一個數據可以向系統發送一個消息。筆者常用的CSerialPort類中就是這樣的處理過程。CSerialPort打開串口後開啟線程監視串口的數據接收,將接收的數據保存到緩沖區,並向父進程發送接收數據的消息,數據將隨消息一起發送到父進程。父進程中開啟此消息的處理函數,從中獲取串口數據後就可以把以上的代碼拷貝過來使用。
CSerialPort向父類發送的消息號如下:
#define WM_COMM_RXCHAR WM_USER+7 // A character was received and placed in the input buffer.
因此需要手動添加此消息的響應函數:
afx_msg LONG OnCommunication(WPARAM ch, LPARAM port);
ON_MESSAGE(WM_COMM_RXCHAR, OnCommunication)
響應函數的具體代碼如下:
LONG CWellInfoView::OnCommunication(WPARAM ch, LPARAM port)
{
int retval = 0;
rcvdat = (BYTE)ch;
if(state_machine == 0) // 協議解析狀態機
{
if(rcvdat == 0x55) // 接收到幀頭第一個數據
state_machine = 1;
else
state_machine = 0; // 狀態機復位
}
else if(state_machine == 1)
{
if(rcvdat == 0xAA) // 接收到幀頭第二個數據
state_machine = 2;
else
state_machine = 0; // 狀態機復位
......
5.總結
以上給出的是通信系統運作的基本雛形,雖然簡單,但是可行。實際的通信系統中協議比這個要復雜,而且涉及到數據包響應、命令錯誤、延時等等一系列的問題,在這樣的一個基礎上可以克服這些困難並且實現出較為穩定可靠的系統
⑹ 數據鏈路層的協議都有什麼
數據鏈路層的主要協議有:
1、Point-to-Point Protocal——PPP點到點。
2、Ethernet——乙太網。
3、High-Level Data Link Control Protocal——高級鏈路控制協議。
4、Frame Relay——幀中繼。
5、Asynchronous Transfer Mode——非同步傳輸模式。
隨機訪問協議:
在隨機訪問協議中,不採用集中控制方式解決信息發送的次序問題。所有用戶都可以根據自己的意願隨機發送信息,佔用信道全部速率。在匯流排網中,當有兩個或者多個用戶同時發送信息的時候,就會產生幀的沖突。這導致所有沖突用戶的發送均失敗。
為了解決隨機接入發生的碰撞,每個用戶需要按照一定的規則反復的重傳他的幀。知道幀沒有碰撞到通過。
這些規則就是隨機訪問MAC協議。
重用的協議:ALOHA協議,CSMA協議,CSMA/CD協議,CSMA/CA協議
這些協議的核心思想都是:勝利者通過爭用獲得信道,進而獲得信息的發送權,所以說隨機訪問MAC協議,也叫爭用型協議。
MAC採用信道劃分機制,那麼節點之間的通信,要不就是共享空間,要不就共享時間,要不就兩個都共享。
隨機MAC:實質上是一種廣播信道轉化為點到點信道的行為。
因為交換機可以轉發廣播,隨機訪問MAC,可以將廣播轉化為point to point
1.1、ALOHA協議:隨機接入系統協議
1.2、CSMA協議:
如果每個站點在發送前都先偵聽一下公用的信道,那麼發送信道空閑後再發送,那麼將會大大減小沖突的可能。從而提高信道的利用率。
載波偵聽多路訪問(Carrier Sense Multiple Access,CSMA)
CSMA協議對ALOHA協議的一種改進,也就是多了一個載波偵聽裝置。
1.3、CSMA/CD協議:載波偵聽多路訪問/碰撞檢測
是對CSMA協議的改進方案,適用於匯流排型網路或者半雙工網路環境
載波偵聽:也就是發送前先偵聽,每次發送數據之前都要先檢查一下匯流排上是否有其他站點在發送數據,如果有則暫時不要發送數據,等待信道變為空閑的時候再發送。
碰撞檢測:就是一邊發送一邊偵聽,適配器在發送數據的時候變檢測信道上的信號電壓的變化情況,用來判斷自己在發送數據的時候其他站點是否也在發送數據。
CSMA/CD工作流程:先聽後發,邊聽邊發,沖突停發,隨機重發匯流排的傳播時延對CSMA/CD的影響很大,CSMA/CD中的站不能同時發送和接收所以CSMA/CD的乙太網是不進行全雙工通信,只能進行半雙工通信。
1.4、CSMA/CA協議
CSMA/CD協議已經應用在使用有線連接的區域網中,但是要在無線區域網的環境下,卻不能用。
CSMA/CD協議,尤其是碰撞部分,因為無線區域網中,接受信號的強度遠遠小於發送信號的強度。而且在無線介質上信號強度變化范圍很廣,要實現碰撞檢測,那麼在硬體上要花費很大。
在無線通信中,並非所有的站點都可以偵聽到對方,也就是隱蔽站的問題。
CSMA/CA協議,廣泛用於無線區域網。
把碰撞檢測改成了碰撞避免(Collision Avoidance,CA)。
碰撞避免:不是指協議可以完全避免碰撞,而是指協議的設計要盡量減少碰撞的發生概率。
CSMA/CA採用二進制指數退避演算法。通過預約信道,ACK幀,RTS/CTS幀,三種機制來實現碰撞避免
RTS/CTS幀,主要用來解決無線網的隱蔽站問題。
預約信道,ACK幀,都是必須要實現的。
預約信道:發送方在發送數據的同時想起他站點通過告知自己傳輸數據需要的時間長度,方便讓其他站點在這段時間內部發送數據,避免碰撞。
ACK幀:所有站點在正確接收到發送給自己的數據幀後,都需要向發送方應答一個ACK幀。
總結:
CSMA/CA協議的基本思想:發送數據的時候先廣播告知其他節點,讓其他節點在某個時間段內不要發送數據,避免碰撞。
CSMA/CD協議的基本思想:發送前先偵聽,邊發送邊偵聽,一旦出現碰撞馬上停止發送。
輪詢訪問MAC:令牌傳遞協議:
在輪詢訪問中,用戶不能隨機的發送信息,是通過集中控制的監控站,以循環的方式輪詢每個節點。然後決定信道的分配。
當某個節點使用信道的時候,其他節點都不能使用信道。典型的輪詢MAC協議是令牌傳遞協議,令牌環區域網。
令牌傳遞協議:一個令牌在各個節點以一個固定的次序交換。令牌是個特殊的比特組成的幀,當換上的站希望傳遞幀的時候,就必須等待令牌,一旦收到令牌,站點就可以啟動發送幀。
輪詢MAC適合復雜很高的廣播信道,負載很高的信道就是多個節點在同一時刻發送數據概率很大的信道。
如果廣播信道採用隨機MAC,發生沖突的概率很大,而採用輪詢MAC則可以更好滿足各個節點的要求。
輪序的實質:不共享時間,空間。實質上就是在隨機MAC的基礎上,限定了有權利發送數據的節點只能有一個。
即使是廣播信道,都可以通過MAC使得廣播信道邏輯上變成點對點的信道。所以說數據鏈路層研究的是點對點之間的通信。
區域網使用的協議主要在數據鏈路層。
廣域網使用的協議主要在網路層。
也就是說網路中的兩個節點要進行數據交換,節點除了要給出數據外,還要給數據包裝上一層控制信息,用來實現檢錯糾錯的功能。如果這層信息是數據鏈路層的協議控制信息,就叫做使用了數據鏈路的協議,如果這層控制信息是在網路層,就是使用了網路層的協議。
廣域網強調:資源共享。
區域網強調:數據傳輸。
廣域網中一個重要問題:路由選擇和分組轉發。
路由選擇協議:負責搜索分組從某個節點到目的節點的最佳路由,以便構成路由表。
分組轉發:從路由表構造出轉發分組的轉發表。
PPP協議和HDLC協議是目前最常用的兩種廣域網數據鏈路層的面向位元組的協議
PPP協議(Point to Point Protocol):
使用串列線路通信的面向位元組的協議,PPP協議應用在直接連接的兩個節點的連路上。
目的:通過撥號或者專線方式建立點對點的連接放鬆數據,讓它成為各種主機,網橋,路由器之間簡單連接的解決方法。
PPP協議:在SLIP的基礎上發展而來,可以在非同步線路上傳輸,也可以在同步線路上用。
不僅用於Modem鏈路,還可以用於路由器和路由器之間的鏈路。
PPP組成:
鏈路控制協議LCP:用來建立,配置,測試,管理數據鏈路。
網路控制協議NCP:由於PPP可以同時用多種網路層協議,每個不同的網路層協議要用一個相應的NCP來配置。一個將IP數據報封裝到串列鏈路的方法。
PPP幀和HDLC幀的格式一樣,收尾都是相同的標志欄位為7E。
PPP協議是點對點的,不是匯流排型,不用CSMA/CD協議。
HDLC協議:
高級數據鏈路控制(High-level Data Link Control):面向比特的數據鏈路層協議。
HDLC協議不依賴任何一種字元集編碼,數據報文可以透明傳輸。
PPP是面向位元組的,HDLC協議是面向比特的。
TCP/IP協議簇:TCP,IP,ICMP,ARP,RARP,UDP,DNS,FTP,HTTP。
HDLC,PPP是ISO提出的數據鏈路層協議,不屬於TCP/IP協議簇。
(6)數據協議擴展閱讀:
數據鏈路層比較:
適用場合:
就系統結構而言,HDLC適用於點到點或點到多點式的結構,BSC同樣也能適用於這些結構;就工作方式而方,HDLC適用於半雙工或全雙工,而BSC則更適用於半雙工方式(也可擴充為全雙工);就傳輸方式而言,BSC和HDLC兩者都只用於同步傳輸。
在傳輸速率方面,BSC和HDLC雖然都沒有限制,但由於它們各自的特點所定,通常BSC用於低、中速傳輸,而HDLC則常用於中、高速傳輸。
傳輸效率:
HDLC開始發送一幀後,就要連續不斷地發完該幀,而BSC的同一數據塊中的不同字元之間可能有時間間隔,這些間隔用SYN字元填充。HDLC可以同時確認幾個幀,而BSC則在發完一數據塊後必須要等待確認(即「停一等」方式)。
HDLC中的每個幀都含有地址欄位A,在多點結構中,每個從站只接收含有本站地址的幀,因此,主站在選中一個從站並與之通信的同時,不用拆鏈,便可選擇其它的站通信,即同時與多個站建立鏈路。
而在BSC中,從建鏈開始,兩站之間的鏈路通道就一直保持到傳輸結束為止。由於以上特點,HDLC的傳輸效率高於BSC的傳輸效率。
傳輸可靠性:
HDLC中所有的幀(包括響應幀)都有FCS,在BSC的監控報文中只有字元校驗能力而無塊校驗能力。HDLC中的I幀按窗口序號順序編號,BSC的數據塊不編號。由於以上特點,HDLD的傳輸可靠性比BSC高。
數據透明性:
HDLC採用「0比特插入法」對數據實現透明傳輸,傳輸信息的比特組合模式無任何限制。BSC用DLE字元填充法來實現透明傳輸,依賴於採用的字元編碼集,且處理復雜。
信息傳輸格式:
HDLC採用統一的幀格式來實現數據、命令、響應的傳輸,實施起來方便。而BSC的格式不統一,數據傳送、正反向監控各規定了一套格式,給實施帶來了不便
鏈路控制:
HDLC利用改變一幀中的控制欄位的編碼模式來完成各種規定的鏈路操作功能,提供的是面向比特的傳輸功能。BSC則是通過改變控制字元來完成鏈路操作功能,提供的是面向字元的傳輸功能。
參考資料來源:網路-數據鏈路層
⑺ 如何實現一個最簡單的通信協議
協議一般要包含:起始符、、數據、校驗碼、結束符,5個部分的定義。其中 起始符、結束符,不能與其他數據重碼。如只要傳輸字母與數字,可以看下ASCII碼表,使用非數字和字母的符號做起始結束符即可,如{};數據長度碼即表示此串數據包的數據長度,如果傳輸的數據串長度固定可省去;校驗碼相當於對此串數據正確性的校驗,和奇偶校驗效果類似,一般是和校驗,即將數據全部累加得到一個和值當校驗碼,接收方收到數據也做一樣的運算與收到的檢驗碼比較,相等就說明正確接收。如要發{1234567890 }換成16進制即:7B 10 31 32 33 34 35 36 37 38 39 30 25 7D;31~30是數據,7B,7D分別為起始和結束符,10為數據長度的BCD碼,25是校驗碼,是31~30的和模100後的BCD碼,轉成BCD碼是為了避免與 起始和結束符重碼。
⑻ 用戶數據報文協議udp屬於什麼協議
傳輸層無連接協議
速度快,但不能保證不丟包和按順序到達,不可靠協議
需要程序員在上層協議中實現可靠性
⑼ 網路協議中那些屬於數據鏈路層協議
很多教科書和培訓教材上,都把arp協議劃分到網路層。我想主要的原因在內於arp協議容屬於tcp/ip協議簇,而在tcp/ip模型中,所有定義的協議至少是在網際層(或稱網路層,ip層)。
但是,按照osi的標准,當數據向下傳遞時,每層會加上自己的信息,各層互不幹擾.這樣當網路層的ip包進入鏈路層時,鏈路層該如何加這個頭部的目標信息呢?它要依靠arp協議來完成.顯然如何加鏈路頭並不是網路層的功能.而且,arp協議工作時,並不使用ip的包頭。所以也有很多人說,arp是鏈路層的。
可以說,在tcp/ip模型中,arp協議屬於ip層;在osi模型中,arp協議屬於鏈路層。
在sniffer軟體中,捕獲協議數據時,如果使用ip地址是無法捕獲到arp包的,因為ip地址是arp協議的載荷,不在包頭中。但arp協議的載荷中,也並不包含任何上層的ip數據包。所以,構造和使用arp協議的主體理解ip地址。從這個角度考慮,將arp協議劃分到ip層也有一定道理。
我覺得邏輯上應該處於鏈路層,但是在抓包的時候,arp和rarp的數據包是封裝在鏈路層的數據包里