Windows socket error 無法在通訊端執行操作 , 因為系統緩衝區空間不足 , 或是佇列已滿. |
答題得分者是:RaynorPao
|
2007
中階會員 發表:54 回覆:90 積分:98 註冊:2008-08-12 發送簡訊給我 |
各位大大好:
我遇到的問題和這位大大遇到的問題一樣!!! ClientSocket連線的問題!? http://delphi.ktop.com.tw/board.php?cid=168&fid=920&tid=33746 程式有一個 Timer !! (一)、當 ClientSocket 執行與 Server 連線的指令後 ( ClientSocket->Open(); ),Timer 就開始計時。 (二)、一分鐘後發現沒有連不到 Server 時,ClientSocket->Close(); 。 ----> 因為怕 Close(); , ClientSocket 會釋放一些東西,所以等了一分鐘後,再下 Open(); (三)、二分鐘後,ClientSocket->Open();,Timer 又重新開始計時。 (四)、循環以上(二)(三)的動作。 一直的循環!! 當然連上時,就停止這樣的循環,直到 Disconnect 事件觸發,就再繼續這樣的循環。 但當我故意把 server 關掉,讓這程式一直的這樣的在執行,好像二三天後就會出現跟大大一樣的錯誤訊息。 Windows socket error 無法在通訊端執行操作 , 因為系統緩衝區空間不足 , 或是佇列已滿.(10055),on API connect 因此想說 TClientSocket 是不是有清佇列之類的指令,是不是它一直在 open ~~ open ~~ open 但沒清掉它內部運作的佇列造成的??? 各位大大是否有遇過?? 請問要如何解決?? 謝謝您們!! PS: 也參考了 Socket 錯誤碼詳解 這一篇,但還是不知如何解決 http://delphi.ktop.com.tw/board.php?cid=31&fid=77&tid=30956 WSAENOBUFS (10055) 緩衝區過小 WinSock核心無法配置足夠的緩衝區,無法執行該程式。這個錯誤的發生和整個Windows系統資源有關。 如果整個Windows本身可用的資源就很少,所能同時執行的程式也少。也有可能是執行了"不良"的應用程式, 沒有正常的使用和歸還系統資源(如記憶體)。或是某些應用程式的不正常關閉,也會佔用系統資源。 |
RaynorPao
版主 發表:139 回覆:3622 積分:7025 註冊:2002-08-12 發送簡訊給我 |
建議先試試以下的作法,看看是否可行?
(1)ClientSocket1 程式啟動的時候,先 ClientSocket1->Open(); (2)三分鐘後,Timer1 若檢查到連不上 Server,則先做 ClientSocket1->Close(); (3)再重新做一次 ClientSocket1->Open(); (4)循環以上(2)(3)的動作
------
-- 若您已經得到滿意的答覆,請適時結案!! -- -- 欲知前世因,今生受者是;欲知來世果,今生做者是 -- -- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 -- |
2007
中階會員 發表:54 回覆:90 積分:98 註冊:2008-08-12 發送簡訊給我 |
謝謝 RaynorPao 大大!! (2)三分鐘後,Timer1 若檢查到連不上 Server,則先做 ClientSocket1->Close(); 這步驟我也有做,只是忘了寫上去!!! ===================引 用 RaynorPao 文 章=================== 建議先試試以下的作法,看看是否可行? (1)ClientSocket1 程式啟動的時候,先 ClientSocket1->Open(); (2)三分鐘後,Timer1 若檢查到連不上 Server,則先做 ClientSocket1->Close(); (3)再重新做一次 ClientSocket1->Open(); (4)循環以上(2)(3)的動作 |
zhgwbzhd
一般會員 發表:10 回覆:32 積分:18 註冊:2008-07-24 發送簡訊給我 |
|
zhgwbzhd
一般會員 發表:10 回覆:32 積分:18 註冊:2008-07-24 發送簡訊給我 |
|
RaynorPao
版主 發表:139 回覆:3622 積分:7025 註冊:2002-08-12 發送簡訊給我 |
(1)理論上應該不會產生這個錯誤,因為當 ServerSocket1 正常運作,且網路也正常的話,ClientSocket1->Open(); 自然可以與 ServerSocke1 建立連線,這個時候才會佔用系統的資源,你可以利用以下的方法驗證(實驗的環境是 Client 和 Server 在同一台主機,且 Server Listen Port 4000):
[code cpp] // Server 端的程式碼 // Unit1.cpp //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ServerSocket1->Port=4000; ServerSocket1->Open(); } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1() { ServerSocket1->Close(); } //--------------------------------------------------------------------------- [/code] [code cpp] // Client 端的程式碼 // Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ClientSocket1->Address="127.0.0.1"; ClientSocket1->Port=4000; ClientSocket1->Open(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { ClientSocket1->Close(); } //--------------------------------------------------------------------------- [/code] (2)把以上 Server 端及 Client 端的程式分別 Run 起來之後,先按 Client 端程式的 Button1,若可順利建立連線 (3)開一個命令提示字元視窗(DOS Box),然後執行 Command line: 「netstat -a」,你會發現裡面有兩行,其中「電腦名稱」會是你自己的電腦名稱,而 3397 也會因 Client 端 binding 不同的 Port 而出現其他的數字 [code cpp] C:\netstat -a Active Connections Proto Local Address Foreign Address State ...略... TCP 電腦名稱:4000 localhost:0 LISTENING TCP 電腦名稱:3397 localhost:4000 ESTABLISHED ...略...在此區域輸入程式碼 [/code] (4)以上的兩行,代表 ClientSocket1 binding 3397 Port,連線到 ServerSocket1 Listen 的 4000 Port,而且已經建立連線,這個時候已經佔用系統的資源 (5)接下來,按 Client 端程式的 Button2 結束連線,然後你在命令提示字元視窗(DOS Box),執行 Command line: 「netstat -a」,你會發現裡面的兩行,已經改變 [code cpp] C:\netstat -a Active Connections Proto Local Address Foreign Address State ...略... TCP 電腦名稱:4000 localhost:0 LISTENING TCP 電腦名稱:3397 localhost:4000 TIME_WAIT ...略... [/code] (6)第二行的 State 從 ESTABLISHED 變成 TIME_WAIT,雖然 ClientSocket1 已經主動結束連線,但是這個 3397 Port 還是會被佔用一段時間,直到作業系統來回收這個已經不使用的 Port,你可以嘗試過幾分鐘之後,在命令提示字元視窗(DOS Box),執行 Command line: 「netstat -a」,你會發現裡面的第二行會自動消失,代表已經沒有佔用系統資源 (7)接著你把 Server 端的程式關閉,然後在 Client 端程式按 Button1,可能會出現 10061 的錯誤訊息,這是正常的,因為沒有辦法建立連線,然後在命令提示字元視窗(DOS Box),執行 Command line: 「netstat -a」,你會發現裡面的兩行並不存在,代表沒有佔用任何系統資源 (8)從以上 (1)~(7) 的實驗結果來看,假如你的 Timer 每 3 分鐘執行一次,若 ClientSocket1 沒有辦法與 ServerSocket1 建立連線,理論上應該不會佔用系統的資源;而每一個連線斷線的話,作業系統也會回收這些沒有使用的 Port (9)因此,我建議你是否可以建立像以上這樣的 Client 及 Server 專案,再加上你原本的 Timer 機制,其他的程式碼不要加進來,然後就這樣 Run 個幾天看看,還會不會有同樣的情形發生,如果不會發生的話,那就代表是其他的程式碼造成的,或許要好好檢查程式碼中對記憶體的操作,會比較妥當
------
-- 若您已經得到滿意的答覆,請適時結案!! -- -- 欲知前世因,今生受者是;欲知來世果,今生做者是 -- -- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 -- |
2007
中階會員 發表:54 回覆:90 積分:98 註冊:2008-08-12 發送簡訊給我 |
謝謝大大的回應!!
這幾天嚐試的寫一個單純的測試程式,但還是會出現此問題。 程式如下: http://delphi.ktop.com.tw/download.php?download=upload/49067209e07dd_ClientSocket.rar 不知大大是否能幫小弟找出問題!! 因為主要是在連不到對方的情況下發生,所以程式中故意連到一個對方(SERVER)不開啟的 PORT 。 謝謝!! ===================引 用 RaynorPao 文 章=================== (1)理論上應該不會產生這個錯誤,因為當 ServerSocket1 正常運作,且網路也正常的話,ClientSocket1->Open(); 自然可以與 ServerSocke1 建立連線, 這個時候才會佔用系統的資源,你可以利用以下的方法驗證(實驗的環境是 Client 和 Server 在同一台主機,且 Server Listen Port 4000): [code cpp] // Server 端的程式碼 // Unit1.cpp //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ServerSocket1->Port=4000; ServerSocket1->Open(); } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1() { ServerSocket1->Close(); } //--------------------------------------------------------------------------- [/code] [code cpp] // Client 端的程式碼 // Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ClientSocket1->Address="127.0.0.1"; ClientSocket1->Port=4000; ClientSocket1->Open(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { ClientSocket1->Close(); } //--------------------------------------------------------------------------- [/code] (2)把以上 Server 端及 Client 端的程式分別 Run 起來之後,先按 Client 端程式的 Button1,若可順利建立連線 (3)開一個命令提示字元視窗(DOS Box),然後執行 Command line: 「netstat -a」,你會發現裡面有兩行,其中「電腦名稱」會是你自己的電腦名稱,而 3397 也會因 Client 端 binding 不同的 Port 而出現其他的數字 [code cpp] C:\netstat -a Active Connections Proto Local Address Foreign Address State ...略... TCP 電腦名稱:4000 localhost:0 LISTENING TCP 電腦名稱:3397 localhost:4000 ESTABLISHED ...略...在此區域輸入程式碼 [/code] (4)以上的兩行,代表 ClientSocket1 binding 3397 Port,連線到 ServerSocket1 Listen 的 4000 Port,而且已經建立連線,這個時候已經佔用系統的資源 (5)接下來,按 Client 端程式的 Button2 結束連線,然後你在命令提示字元視窗(DOS Box),執行 Command line: 「netstat -a」,你會發現裡面的兩行,已經改變 [code cpp] C:\netstat -a Active Connections Proto Local Address Foreign Address State ...略... TCP 電腦名稱:4000 localhost:0 LISTENING TCP 電腦名稱:3397 localhost:4000 TIME_WAIT ...略... [/code] (6)第二行的 State 從 ESTABLISHED 變成 TIME_WAIT,雖然 ClientSocket1 已經主動結束連線,但是這個 3397 Port 還是會被佔用一段時間,直到作業系統來回收這個已經不使用的 Port,你可以嘗試過幾分鐘之後,在命令提示字元視窗(DOS Box),執行 Command line: 「netstat -a」,你會發現裡面的第二行會自動消失,代表已經沒有佔用系統資源 (7)接著你把 Server 端的程式關閉,然後在 Client 端程式按 Button1,可能會出現 10061 的錯誤訊息,這是正常的,因為沒有辦法建立連線,然後在命令提示字元視窗(DOS Box),執行 Command line: 「netstat -a」,你會發現裡面的兩行並不存在,代表沒有佔用任何系統資源 (8)從以上 (1)~(7) 的實驗結果來看,假如你的 Timer 每 3 分鐘執行一次,若 ClientSocket1 沒有辦法與 ServerSocket1 建立連線,理論上應該不會佔用系統的資源;而每一個連線斷線的話,作業系統也會回收這些沒有使用的 Port (9)因此,我建議你是否可以建立像以上這樣的 Client 及 Server 專案,再加上你原本的 Timer 機制,其他的程式碼不要加進來,然後就這樣 Run 個幾天看看,還會不會有同樣的情形發生,如果不會發生的話,那就代表是其他的程式碼造成的,或許要好好檢查程式碼中對記憶體的操作,會比較妥當 |
RaynorPao
版主 發表:139 回覆:3622 積分:7025 註冊:2002-08-12 發送簡訊給我 |
(1)我花了一點時間看你的程式,跟我之前建議你用來釐清問題,較簡單版本的專案,似乎也差異太大了吧
(2)裡面用了三個 Timer 來控制 TClientSocket Array (size 250),這樣當然比較不容易找到問題,而我也沒有足夠的時間幫你看完程式 (3)不過依照你的描述,在連線一直無法建立的情形持續一段時間後,就會發生你所說的問題,我看到你的程式碼在 Timer 裡動態 new TClientSocket,但是無法連線的時候,卻沒有把它 delete,也就是在 try 裡面 new,若 catch 到 exception 的話,要把它 delete 掉,這樣才不會造成系統資源的佔用,直到系統資源被耗盡為止 (4)建議你再重新調整你的程式架構,調整完之後,要做驗證的工作,要如何驗證呢?很簡單,就是把你的程式 run 起來之後,然後把工作管理員打開,觀察你的執行檔的記憶體使用情況,如果記憶體的使用情況會一直持續成長,那代表你的程式還是有問題,請再做修正,一直反覆此作法,直到記憶體不會一直持續成長為止;否則,你的問題是無法避免的
------
-- 若您已經得到滿意的答覆,請適時結案!! -- -- 欲知前世因,今生受者是;欲知來世果,今生做者是 -- -- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 -- |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |