用過psock模組的都知道PSOCK_SEND()的功能是向指定的socket輸出指定的位元組資料,然而,代碼中的疏漏使得它無法實現發送大於uip_mss()個位元組數.這是因為:
PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));語句第一次執行時,通過send_data(s)把第一個資料包發送到網路.而第二次執行以發送後續資料時,如果uip_acked()成立,那麼data_acked(s)也成立,接著繼續執行send_data(s)發送後續資料,此時send_data(s)也成立,所以PT_WAIT_UNTIL()的等待條件成立,此時執行外圍的while(s->sendlen > 0){}迴圈將再次執行PT_WAIT_UNTIL().由於PT_WAIT_UNTIL()會再次調用data_acked(s) 和 send_data(s),這時導致了問題.因為uip_acked()標誌還是返回ture值,也就是說條件(data_acked(s) & send_data(s))總是成立,PT_WAIT_UNTIL()宏也就沒有機會執行return語句,直到把要發送的資料折騰完!所以,後續的資料並沒有發送出去,雖然調用了send_data(s),它只是完成資料到緩衝區的拷貝而已.大家知道,uip的資料要發送到網路,必須要從UIP_APPCALL()返回之後才行!
以上的疏漏導致的結果是:用PSOCK_SEND()發送10000位元組的資料,只能發送出去最前面的uip_mss()個,而後續的位元組並不會發送出去!
該錯誤同樣影響到PSOCK_SEND_STR()和PSOCK_GENERATOR_SEND()!
解決的辦法是在data_acked(s)函數的if(s->state == STATE_DATA_SENT && uip_acked()){}代碼塊內清除uip_flags變數的UIP_ACKDATA位, 修改後如下:
if(s->state == STATE_DATA_SENT && uip_acked()){
uip_flags &= ~UIP_ACKDATA;
......
}
好了,我已經把該錯誤登記到uip官方網站,希望新版uip會把該錯誤妥善改正,謝謝uip作者!
2009.9.12 xuyao (大家可以加入QQ交流:26750452)