全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1124
推到 Plurk!
推到 Facebook!

關於Twinsoketstream類的write函數

 
AB
高階會員


發表:166
回覆:262
積分:125
註冊:2003-08-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-12-02 00:11:29 IP:61.64.xxx.xxx 未訂閱
關於Twinsoketstream類的write函數 http://www.powerba.com/develop/delphi/article/20011010012.htm 我曾在DELPHI大富翁上發表了以下問題,但回應寥寥。 問題: 我用delphi 3.0c/s 編寫Email用戶端程式,在程式中使用 Twinsocketstream傳送資訊,我先把信件資訊存到一個 stream中,再用Twinsocetstream類函數copyfrom,把字元傳 到Soket上。但是當資訊大於2k或3k時,系統就崩潰, 出現藍屏, 我察看了Twinsocketstream的源碼,發現 wirte函數是完成copyfrom功能的主要函數, 在write函數裏有一句代碼是: if not WriteFile(FSocket.SocketHandle, Buffer, Count, Integer(Result), @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then 據我理解這裏使用了非同步寫操作,關鍵是Overlapped 的使用,當我把Overlapped參數改d零,並對後面 有關非同步寫操作的代碼進行了修改,即改d 阻塞同步寫操作,再次運行程式,轉送一個1M多 的Attach file ,也能運行通過。 我不知道這是d甚l,請各位給我指教,並詳細 講一下wirtefile API函數裏的overlap參數的具體含義 與用法。 有關此問題的補充: 這兩天,過節有了充裕時間來研究這個問題,我又仔細地分析了twinsocketstre am.write 函數的源代碼,發現它的代碼與twinsocketstream.read函數的代相似,但是write與read 相比在GetOverlappedResult(FSocket.SocketHandle, Overlapped, Integer(Re sult), false);語 句後少了一個fevent.resetevent;語句。這個語句是用來把時間event設d不發信 號,阻止 與此事件有關的線程(即writefile函數)運行,據我所知,winsocket自己不負 責處理 多線程之間的重入,這必須由程式師自己解決,如果write函數沒有fevent.rese tevent , 那l當我的程式繼續對socket進行操作,例如讀socket時,writefile函數也同時 在對 socket進行寫操作,這就發生了重入,從而使得winsocket崩潰,即使能關閉有問 題的 程式,winsocket也無法使用了,除非重均C 這種分析能夠解釋我在編程中碰到的現象。 我把fevent.resetevent加到write函數中去,用我編的email程式發送幾個長達1 M的附件, 發現在發送一個附件時,程式能夠正常運行,當我的程式創建了四個線程,同時 發送四 個附件時,老問題又出來了。看來真是好事多磨,我發現 if FEvent.WaitFor(FTimeOut) <> wrSignaled then Result := 0; 也有上述的問題,我在程式中設定的ftimeout是2000,即2秒,當我同時發送多 個附 件時,socket有些繁忙,2秒過後可能writefile還沒有完成操作,這個判斷就成 立了, 但是這裏面少了fevent.resetevent,於是用樣的問題就又出來了。解決的辦法是 ,加入 fevent.resetevent。不過如果想讓程式正常運行必須加大ftimeout值,這個值在 編程時應 預留介面,讓使用者根據網路情況自己設定。 綜上所述,delphi3/cs在此有bug ,不知delphi4.0是否加以了改進。 另外,我認 d這裏 雖然使用了writefile的非同步功能,但是並沒有充分利用非同步特性,而只是簡單地 有waitfor 進行等待,這與twinsocketstream本身是阻塞的socket有關,這裏使用了非同步寫 操作唯 一的作用是引入了timeout, 避免因網路阻塞writefile長時間無法返回,給程式 一個撤 銷寫操作的機會。 最後我把修改後的write 與read函數附在這裏,請大家參考。 談了這l多,不知道自己對不對,請萓麆炊漇教。 function TWinSocketStream.Read(var Buffer; Count: Longint): Longint; var Overlapped: TOverlapped; ErrorCode: Integer; begin FSocket.Lock; try FillChar(OVerlapped, SizeOf(Overlapped), 0); Overlapped.hEvent := FEvent.Handle; if not ReadFile(FSocket.SocketHandle, Buffer, Count, Integer(Resul t), @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then begin ErrorCode := GetLastError; raise ESocketError.CreateFmt(sSocketIOError, [sSocketRead, Error Code, SysErrorMessage(ErrorCode)]); end; if FEvent.WaitFor(FTimeOut) <> wrSignaled then begin Result := 0; FEvent.ResetEvent; end else begin GetOverlappedResult(FSocket.SocketHandle, Overlapped, Integer(Re sult), False); FEvent.ResetEvent; end; finally FSocket.Unlock; end; end; function TWinSocketStream.Write(const Buffer; Count: Longint): Longint ; var Overlapped: TOverlapped; ErrorCode: Integer; begin FSocket.Lock; try FillChar(OVerlapped, SizeOf(Overlapped), 0); Overlapped.hEvent := FEvent.Handle; if not WriteFile(FSocket.SocketHandle, Buffer, Count, Integer(Resu lt), @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then begin ErrorCode := GetLastError; raise ESocketError.CreateFmt(sSocketIOError, [sSocketWrite, Erro rCode, SysErrorMessage(ErrorCode)]); end; if FEvent.WaitFor(FTimeOut) <> wrSignaled then begin Result := 0; fevent.resetevent; end else begin GetOverlappedResult(FSocket.SocketHandle, Overlapped, Integer(Re sult),false); FEvent.ResetEvent; end; finally FSocket.Unlock; end; end;
系統時間:2024-05-04 6:34:06
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!