lwip翻译的最好的一个

[复制链接]
5415|0
 楼主| high 发表于 2007-2-13 12:02 | 显示全部楼层 |阅读模式
刚刚完成win32下的lwip移植调试测试程序。<br /><br />使用winpcap做底层。<br /><br />只要电脑&nbsp;不需要额外硬件就可以马上测试lwip.以后可能可以给大家汇报测试结果<br /><br /><br /><br />---------------------------------------------------------------<br />Raw&nbsp;TCP/IP&nbsp;interface&nbsp;for&nbsp;lwIP&nbsp;0.5<br /><br />lwIP&nbsp;0.5&nbsp;中的原始&nbsp;TCP/IP&nbsp;介面<br /><br />&nbsp;<br /><br />&nbsp;<br /><br />作者:Adam&nbsp;Dunkels,2001/12/12<br /><br />譯者:ct小貓&nbsp;(Elisha&nbsp;Chou周錦廷&nbsp;ct@ccns.ncku.edu.tw)<br /><br />&nbsp;<br /><br />--<br /><br />譯注:2004年8月,lwIP已釋出1.0.0版,但本文仍有相當的參考價值。待譯者有空時,將會針對最近版本的差異處進行修改。(當然若有朋友願意指教,更是感激不盡。)<br /><br />&nbsp;<br /><br />原文請見:<br /><br />http://ccns.ncku.edu.tw/~ct/doc/lwIP/lwIP_Raw_TCPIP.htm<br /><br />--<br /><br />&nbsp;<br /><br />lwIP&nbsp;提供了兩組&nbsp;API&nbsp;,讓程式和&nbsp;TCP/IP&nbsp;程式碼之間進行溝通:循序性API&nbsp;(Sequential&nbsp;API,通常我們可以就稱呼它為“the&nbsp;API”。)(譯注:以下譯文將配合文句流暢性,來決定是否保留原文或簡稱。)與原始TCP/IP介面&nbsp;(raw&nbsp;TCP/IP&nbsp;interface)。本文件將對後者進行描述。至於lwIP&nbsp;0.5以下的版本的API,尚未有文件說明。<br /><br />&nbsp;<br /><br />「循序性API」為一般循序程式提供了使用&nbsp;lwIP&nbsp;stack&nbsp;的途徑。它與BSD的socket&nbsp;API頗為類似。它的執行模式是建立在「開啟→讀取→寫入→關閉」這個典範的基礎之上。由於此種方式中,TCP/IP&nbsp;stack事件的基礎乃是其固有的自然天性,因此TCP/IP程式碼和應用程式必定分別存在於「不同的execution&nbsp;context(亦即不同的執行緒)」當中。<br /><br />&nbsp;<br /><br />「原始TCP/IP介面」讓應用程式可以和TCP/IP程式碼更緊密地結合在一起。程式的執行會變成一個在TCP/IP程式碼中進行callback&nbsp;函式呼叫的事件。這時候,TCP/IP程式碼和應用程式會變成「在同一個執行緒中執行」。相較之下,循序性API的負擔太高,實在不適合小型系統的開發,因為它強迫應用程式遵守多執行緒的典範。<br /><br />&nbsp;<br /><br />使用原始TCP/IP介面,不僅讓程式的執行速度加快,也可以舒緩記憶體的激烈競爭。但「缺點」是程式開發的難度多少增加了一些,而使用原始TCP/IP介面的程式也會更難理解。然而,對於需要在程式大小和記憶體用量上精簡的應用而言,這仍然是個建議的方式。<br /><br />&nbsp;<br /><br />我們可以同時在不同的應用程式中使用這兩種不同的API。事實上,循序性API就是原始TCP/IP介面的一個應用程式實作。&nbsp;J<br /><br />&nbsp;<br /><br />---&nbsp;Callbacks<br /><br />&nbsp;<br /><br />程式的執行,是由callback&nbsp;所趨動的。每個callback都是TCP/IP程式碼中呼叫的一個普通C函式。每個callback函式接受一組TCP或UDP連線狀態作為參數。另外,為了追蹤程式的特定狀態,在呼叫callback函式時也會傳入一個獨立於TCP/IP狀態的程式指定參數。<br /><br />&nbsp;<br /><br />用來設定應用程式連線狀態的函式是:<br /><br />void&nbsp;tcp_arg(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;void&nbsp;*arg)<br /><br />它指定了要傳遞給所有其他callback函式的程式特定狀態。pcb代表目前TCP連線的control&nbsp;block(控制區塊),而arg則是要傳入callback的參數。<br /><br />&nbsp;<br /><br />---&nbsp;TCP/IP連線設定<br /><br />&nbsp;<br /><br />用來將連線設置妥當的函式和循序性API以及BSD&nbsp;socket&nbsp;API中同樣用途的函式十分相似。先用tcp_new()來建立一個新的TCP&nbsp;connection&nbsp;identifier(連線標籤)(也就是一個PCB,protocol&nbsp;control&nbsp;block)。接著我們可以設定這個PCB,讓它負責傾聽外部連進來的連線,或者是主動連接另外一個host。<br /><br />&nbsp;<br /><br />struct&nbsp;tcp_pcb&nbsp;*tcp_new(void)<br /><br />這個函式建立一個新的TCP&nbsp;connection&nbsp;identifier&nbsp;(也就是建立一個新的PCB)。假如配置memory給PCB的過程失敗,就傳回null。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_t&nbsp;tcp_bind(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;struct&nbsp;ip_addr&nbsp;*ipaddr,u16_t&nbsp;port)<br /><br />這個函式將PCB與本地端的IP位址及埠號&nbsp;bind在一起。將IP位址指定為IP_ADDR_ANY能讓它和所有的本地端IP位址連線bind起來。<br /><br />&nbsp;<br /><br />假如另一個連線也嘗試bind相同的埠號,它會傳回ERR_USE,否則傳回ERR_OK。<br /><br />&nbsp;<br /><br />struct&nbsp;tcp_pcb&nbsp;*tcp_listen(struct&nbsp;tcp_pcb&nbsp;*pcb)<br /><br />令PCB開始傾聽連進來的連線。一旦接受某個連線要求,tcp_accept()所指定的函式會被呼叫起來。PCB必需用tcp_bind()來和本地端的某個埠bind在一起。<br /><br />&nbsp;<br /><br />tcp_listen()會傳回一個新的connection&nbsp;identifier,原本被當成參數傳入function的那一個connection&nbsp;identifier則會被釋放掉。這樣做的理由是,一個負責傾聽的connection所需的記憶體極少,所以tcp_listen()會修正原始連線的記憶體需求,配置一塊較小的記憶體區塊給這個負責傾聽的connection。<br /><br />&nbsp;<br /><br />假如沒有足夠的memory以供配置給這個connection,tcp_listen()將傳回NULL。那麼原本當成參數傳入tcp_listen()的PCB就不會被釋放掉。<br /><br />&nbsp;<br /><br />void&nbsp;tcp_accept(struct&nbsp;tcp_pcb&nbsp;*pcb,err_t&nbsp;(*&nbsp;accept)(void&nbsp;*arg,&nbsp;struct&nbsp;tcp_pcb&nbsp;*newpcb,err_t&nbsp;err))<br /><br />指定在listening&nbsp;connection中,一旦建立了新的connection,要去呼叫哪個callback函式。<br /><br />&nbsp;<br /><br />err_t&nbsp;tcp_connect(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;struct&nbsp;ip_addr&nbsp;*ipaddr,u16_t&nbsp;port,&nbsp;err_t&nbsp;(*&nbsp;connected)(void&nbsp;*arg,struct&nbsp;tcp_pcb&nbsp;*tpcb,&nbsp;err_t&nbsp;err));<br /><br />將PCB連接遠端host的資訊設置妥當,傳送一個開啟連線的初始SYN值。<br /><br />&nbsp;<br /><br />tcp_connect()會立刻return一個值,而不會等到連線資料全部設定妥當才return。當連線建立時,它會呼叫第四個參數&nbsp;(connected參數)&nbsp;所指的函式。假如連線無法正確建立,可能是因為對方host拒絕連線,或是沒有收到該host的回應,那麼&nbsp;“connected”&nbsp;函式仍將被呼叫,並傳入相對應的err參數。<br /><br />&nbsp;<br /><br />假如沒有可用的memory供SYN值的queue使用,tcp_connect()會傳回ERR_MEM。假如SYN值enqueue的動作成功了,tcp_connect()就傳回ERR_OK。<br /><br />&nbsp;<br /><br />---&nbsp;傳送TCP&nbsp;data<br /><br />&nbsp;<br /><br />TCP&nbsp;data的傳送,是藉由tcp_write()的呼叫來enqueue&nbsp;data。一旦資料成功傳送到遠端主機,應用程式會被通知執行一個指定的callback函式。<br /><br />&nbsp;<br /><br />err_t&nbsp;tcp_write(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;void&nbsp;*dataptr,&nbsp;u16_t&nbsp;len,&nbsp;u8_t&nbsp;copy)<br /><br />它會將dataptr所指的data&nbsp;enqueue起來。Data的長度由len參數指定。copy參數的值可以是0或1,代表是否要重新配置一塊記憶體,並將data複製過去。假如copy的值是0,就不會配置新的記憶體,只利用指標將data所在的位址記錄下來。<br /><br />&nbsp;<br /><br />假如資料長度超過傳送用的buffer大小,或者寄送區段的queue長度超過lwipopts.h中定義的上限,tcp_write()的執行將會失敗,並傳回ERR_MEM。Output&nbsp;queue可用的位元組數量可以透過tcp_sndbuf()函式來修改。<br /><br />&nbsp;<br /><br />這個函式的正確操作方式,是傳給它的data不應超過tcp_sndbuf()所定的量。假如它傳回ERR_MEM,應用程式應當等待目前queue裡面的部分資料成功地傳送到對方主機,然後再試一次。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />---&nbsp;接收TCP&nbsp;data<br /><br />&nbsp;<br /><br />TCP&nbsp;data的接收是以callback為基礎──當新的資料到達時,一個應用程式指定的callback函式會被喚起。應用程式接收data之後,要呼叫tcp_recved()來通知TCP去擴張它的receive&nbsp;window並advertise。<br /><br />&nbsp;<br /><br />void&nbsp;tcp_recv(struct&nbsp;tcp_pcb&nbsp;*pcb,err_t&nbsp;(*&nbsp;recv)(void&nbsp;*arg,&nbsp;struct&nbsp;tcp_pcb&nbsp;*tpcb,struct&nbsp;pbuf&nbsp;*p,&nbsp;err_t&nbsp;err))<br /><br />設定新資料抵達時,所要呼叫的callback函式。如果對這個callback函式傳入指向NULL值的pbuf,就代表遠端主機已關閉連線。<br /><br />&nbsp;<br /><br />void&nbsp;tcp_recved(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;u16_t&nbsp;len)<br /><br />通常在應用程式接收完data後呼叫。len參數指示所接收資料的長度。<br /><br />&nbsp;<br /><br />---&nbsp;應用程式輪詢&nbsp;(polling)<br /><br />&nbsp;<br /><br />當連線idle住的時候(也就是這時候既沒有資料在傳送,也沒有資料在接收),lwIP會藉著呼叫某個特定的callback函式,而不斷地輪詢各個應用程式。這個功能可以當做watchdog&nbsp;timer,用來將idle太久的connection殺掉,也可以用來等待可用的記憶體。例如,若呼叫tcp_write()後,因為沒有可用的記憶體而造成失敗,應用程式可以利用polling的功能,在connection&nbsp;idle一段時間後,再度喚起tcp_write()。<br /><br />&nbsp;<br /><br />void&nbsp;tcp_poll(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;u8_t&nbsp;interval,err_t&nbsp;(*&nbsp;poll)(void&nbsp;*arg,&nbsp;struct&nbsp;tcp_pcb&nbsp;*tpcb))<br /><br />指定輪詢時間間隔,以及用來輪詢應用程式的callback函式。時間間隔通常是用TCP&nbsp;coarse所產生的timer&nbsp;shots(一般來說一秒產生兩次)的倍數來指定。interval是10代表應用程式每隔5秒輪詢一次。<br /><br />&nbsp;<br /><br />---&nbsp;關閉或中斷連線<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_t&nbsp;tcp_close(struct&nbsp;tcp_pcb&nbsp;*pcb)<br /><br />關閉連線。假如關閉連線所需的memory不足,就傳回ERR_MEM,然後應用程式應當等待,並利用acknowledgment&nbsp;callback或輪詢機制重新嘗試。假如成功關閉,就傳回ERR_OK。<br /><br />&nbsp;<br /><br />在呼叫tcp_close()之後,TCP程式碼會釋放掉PCB所佔用的記憶體。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;tcp_abort(struct&nbsp;tcp_pcb&nbsp;*pcb)<br /><br />送一個RST(reset)&nbsp;segment到遠端主機,以便中斷連線。PCB將被釋放。這個函式不會有失敗的情況。<br /><br />&nbsp;<br /><br />假如connection因為某項錯誤而導致中斷,應用程式將會透過err&nbsp;callback而收到警告。會造成中斷的錯誤是像記憶體資源不足這樣的錯誤。錯誤處理的callback函式可以透過tcp_err()來設定。<br /><br />&nbsp;<br /><br />void&nbsp;tcp_err(struct&nbsp;tcp_pcb&nbsp;*pcb,&nbsp;void&nbsp;(*&nbsp;err)(void&nbsp;*arg,err_t&nbsp;err))<br /><br />由於錯誤發生時,PCB可能早已被釋放掉,所以錯誤處理的callback函式並不需要接受PCB做為參數。<br /><br />&nbsp;<br /><br />---&nbsp;較低階的TCP介面<br /><br />&nbsp;<br /><br />TCP為低階系統提供了一個簡單的介面。在系統初始化時,tcp_init()必須在任何其他的TCP函式被呼叫前先執行。系統執行的過程中必須定期地呼叫tcp_fasttmr()和tcp_slowtmr()這兩個計時器函式。tcp_fasttmr()的執行時間間隔是TCP_FAST_INTERVAL&nbsp;milliseconds(定義在tcp.h中),而tcp_slowtmr()則是每隔TCP_SLOW_INTERVAL&nbsp;milliseconds呼叫一次。<br /><br />&nbsp;<br /><br />---&nbsp;UDP介面<br /><br />&nbsp;<br /><br />UDP介面與TCP介面相似,但是因為UDP的複雜性較低,因此介面也顯得簡單多了。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;udp_pcb&nbsp;*udp_new(void)<br /><br />建立新的UDP&nbsp;PCB以供UDP溝通用。PCB在與本地端位址bind起來、或是連接到遠端位址之後,才進入active狀態。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;udp_remove(struct&nbsp;udp_pcb&nbsp;*pcb)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;移除並釋放所有的PCB。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_t&nbsp;udp_bind(struct&nbsp;udp_pcb&nbsp;*pcb,&nbsp;struct&nbsp;ip_addr&nbsp;*ipaddr,u16_t&nbsp;port)<br /><br />將PCB與本地端位址bind在一起。將ipaddr設為IP_ADDR_ANY代表它將監聽任何的本地端位址。這個函式目前的傳回值一律是ERR_OK。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_t&nbsp;udp_connect(struct&nbsp;udp_pcb&nbsp;*pcb,&nbsp;struct&nbsp;ip_addr&nbsp;*ipaddr,u16_t&nbsp;port)<br /><br />設定PCB的遠地端。這個函式不會造成任何網路流量,只會設定PCB的遠端位址欄位。<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_t&nbsp;udp_send(struct&nbsp;udp_pcb&nbsp;*pcb,&nbsp;struct&nbsp;pbuf&nbsp;*p)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;傳送packet&nbsp;buffer&nbsp;p。它不會釋放掉pbuf。<br /><br />&nbsp;<br /><br />void&nbsp;udp_recv(struct&nbsp;udp_pcb&nbsp;*pcb,void&nbsp;(*&nbsp;recv)(void&nbsp;*arg,&nbsp;struct&nbsp;udp_pcb&nbsp;*upcb,struct&nbsp;pbuf&nbsp;*p,struct&nbsp;ip_addr&nbsp;*addr,u16_t&nbsp;port),void&nbsp;*recv_arg)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指定UDP&nbsp;diagram接收完成後,應當呼叫的callback函式。<br /> 相关链接:<a href='http://ccns.ncku.edu.tw/~ct/doc/lwIP/lwIP_Raw_TCPIP_ch.htm'>http://ccns.ncku.edu.tw/~ct/doc/lwIP/lwIP_Raw_TCPIP_ch.htm</a>
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

1078

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部