亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? svrsocket,cltsocket控件源碼.htm

?? ServerSocket,ClientSocket控件源碼,講述內部實現原理
?? HTM
?? 第 1 頁 / 共 3 頁
字號:
      <br>
          else DoListen(QueueSize);<br> 
      <br>
        end;<br>
      <br>
    end;<br>
      <br>
    if FLookupState &lt;> lsIdle then<br> 
      <br>
      ASyncInitSocket(Name, Address, Service, Port, QueueSize, Client);//遞歸<br> 
      <br>
  except<br>
      <br>
    Disconnect(FSocket);<br>
      <br>
    raise;<br>
      <br>
  end;<br>
      <br>
      end;<br>
      <br>
      它從判斷FLookupState的狀態來執行相應的操作,而最后每一步都會執行到,它是怎么做到的呢,答案就是最后的這兩句:<br>
      <br>
      if FLookupState &lt;> lsIdle then<br> 
      <br>
      ASyncInitSocket(Name, Address, Service, Port, QueueSize, Client);<br> 
      <br>
      我們先從頭來看吧:<br>
      <br>
      首先,FLookupState的狀態行為lsIdle,則執行isIdle這一大塊,判斷Client的值,這里是服務端,所以應該為False(從調用該方法的函數也可得知),所以只執行了這一塊:<br>
      <br>
      FLookupState := lsLookupAddress;<br> 
      <br>
      FAddr.sin_addr.S_addr := INADDR_ANY;<br> 
      <br>
      其余都是對于客戶端的來作的,所以以后再討論它(由此也可以知道該函數的重要性了)。<br>
      <br>
      還記得INADDR_ANY的意義嗎,它會使得WinSock自動加入正確的地址。<br>
      <br>
      好,方法執行到最后的這幾句:<br>
      <br>
      if FLookupState &lt;> lsIdle then<br> 
      <br>
      ASyncInitSocket(Name, Address, Service, Port, QueueSize, Client);<br> 
      <br>
      這時FLookupState已經為lsLookupAddress了,所以又會調用ASyncInitSocket方法,它就是這樣遞歸調用本身,直到所有操作都完畢,這樣的設計思維實在是太精巧了。<br>
      <br>
      第一遞歸之后,它又執行了那一塊呢,當然是lsLookupAddress:這一塊啦,看看代碼,知道它會先判斷函數的參數Service是否為空,我們前面沒有對該傳遞過來的這個參數并沒有同值,所以為空,便執行了這兩句:<br>
      <br>
      FLookupState := lsLookupService;<br> 
      <br>
      FAddr.sin_port := htons(Port);<br> 
      <br>
      可知,它對結構的端口值了,又進行第二次遞歸,這里應該是執行lsLookupService:這一塊,并調用了這個方法DoListen(QueueSize);開始監聽:<br>
      <br>
      FLookupState := lsIdle;<br> 
      <br>
      if Client then<br> 
      <br>
  DoOpen<br>
      <br>
      else DoListen(QueueSize);<br> 
      <br>
      我們看到FLookupState已經又回到了IsIdle,所以就不再遞歸了。<br>
      <br>
      最好,我們得來看看DoListen這個方法,這個大概就是萬事具務,只欠東風的東風了,我們猜測它會在這里調用Bind和Listen等API,并觸發Oolisten事件:<br>
      <br>
      (2211121)<br>
      <br>
      procedure TCustomWinSocket.DoListen(QueueSize: Integer);<br> 
      <br>
      begin<br>
      <br>
  CheckSocketResult(bind(FSocket, FAddr, SizeOf(FAddr)), 'bind');<br> 
      <br>
  DoSetASyncStyles;<br>
      <br>
  if QueueSize > SOMAXCONN then QueueSize := SOMAXCONN;<br> 
      <br>
  Event(Self, seListen);<br> 
      <br>
  CheckSocketResult(Winsock.listen(FSocket, QueueSize), 'listen');<br> 
      <br>
  FLookupState := lsIdle;<br> 
      <br>
  FConnected := True;<br> 
      <br>
      end;<br>
      <br>
      哈,一切都明朗了,所有API都在這里調用了,事件也觸發了。現在就等客戶來連接了<br>
      <br>
      只是還沒有完,還有一個DoSetASyncStyles方法,堅持走下去吧,會到挑花園的:<br>
      <br>
      (22111211)<br>
      <br>
      procedure TCustomWinSocket.DoSetAsyncStyles;<br> 
      <br>
      var<br>
      <br>
  Msg: Integer;<br> 
      <br>
  Wnd: HWnd;<br> 
      <br>
  Blocking: Longint;<br> 
      <br>
      begin<br>
      <br>
  Msg := 0;<br> 
      <br>
  Wnd := 0;<br> 
      <br>
  if FAsyncStyles &lt;> [] then<br> 
      <br>
  begin<br>
      <br>
    Msg := CM_SOCKETMESSAGE;<br> 
      <br>
    Wnd := Handle;<br> 
      <br>
  end;<br>
      <br>
  WSAAsyncSelect(FSocket, Wnd, Msg, Longint(Byte(FAsyncStyles)));<br> 
      <br>
  if FASyncStyles = [] then<br> 
      <br>
  begin<br>
      <br>
    Blocking := 0;<br> 
      <br>
    ioctlsocket(FSocket, FIONBIO, Blocking);<br> 
      <br>
  end;<br>
      <br>
      end;<br>
      <br>
      有兩個情況,當FAsyncStyles有元素時和沒有元素時,從上面的代碼中我們看到它是有元素的。則:<br>
      <br>
      Msg := CM_SOCKETMESSAGE;<br> 
      <br>
      Wnd := Handle;<br> 
      <br>
      第一句應該是指針Socket消息了,用于與客戶端的讀寫事件的觸發的吧。而第二句,則我仔細看了,Handle是TCustomWinSocket的一個屬性:<br>
      <br>
      property Handle: HWnd read GetHandle;<br> 
      <br>
      再看看GetHandle方法<br>
      <br>
      function TCustomWinSocket.GetHandle: HWnd;<br> 
      <br>
      begin<br>
      <br>
  if FHandle = 0 then<br> 
      <br>
    FHandle := AllocateHwnd(WndProc);<br> 
      <br>
  Result := FHandle;<br> 
      <br>
      end;<br>
      <br>
      我們記得上面并沒有對FHandle進行賦值,所以它應該為0,則調用了AllocateHwnd,這個方法產生一個不可見的窗口用于接收消息,窗口過程就是WndProc,在CustomWinSocket有聲明:<br>
      <br>
      procedure TCustomWinSocket.WndProc(var Message: TMessage);<br> 
      <br>
      begin<br>
      <br>
  try<br>
      <br>
    Dispatch(Message);<br>
      <br>
  except<br>
      <br>
    if Assigned(ApplicationHandleException) then<br> 
      <br>
      ApplicationHandleException(Self);<br>
      <br>
  end;<br>
      <br>
      end;<br>
      <br>
      可以知道,他調用Object的Dispatch(Message);進行消息分配,而我們看到類中有消息函數的聲明:<br>
      <br>
      procedure CMSocketMessage(var Message: TCMSocketMessage); message CM_SOCKETMESSAGE;<br> 
      <br>
      當事件發生時就會調用這些消息處理函數了。而這些消息是從那里發生的呢,得回過頭去看看DoSetAsyncStyles方法,其中有這一個SocketAPI:<br>
      <br>
      WSAAsyncSelect(FSocket, Wnd, Msg, Longint(Byte(FAsyncStyles)));<br> 
      <br>
      就是通過它,當有網絡消息發生的時候,才會觸發上面事件的,而Longint(Byte(FAsyncStyles)<br>
      <br>
      則指定允許觸發哪些事件。(具體的還是看看MSDN的說明吧)<br>
      <br>
      <br>
      <br>
      呼還沒有完嗎,其實差不多了,我們現在知道了當有客戶端連接或讀寫,是通過什么方式來讓服務端知道并觸發相應的事件的,說到底還是用了WinSock的API,只不過Delphi用自己的事件處理方式將那些Socket異步消息轉化成自己的事件了,這個過程是非常精彩的,很值得我們學習。<br>
      <br>
      但現在只剩下最一步了,TCustomWinSocket消息處理方法中,如何轉化為事件,并傳遞到ServerSocket去的呢,答案只有在源代碼中找了:<br>
      <br>
      procedure TCustomWinSocket.CMSocketMessage(var Message: TCMSocketMessage);<br> 
      <br>
      <br>
      <br>
  function CheckError: Boolean;<br> 
      <br>
  var<br>
      <br>
    ErrorEvent: TErrorEvent;<br> 
      <br>
    ErrorCode: Integer;<br> 
      <br>
  begin<br>
      <br>
    if Message.SelectError &lt;> 0 then<br> 
      <br>
    begin<br>
      <br>
      Result := False;<br> 
      <br>
      ErrorCode := Message.SelectError;<br> 
      <br>
      case Message.SelectEvent of<br> 
      <br>
        FD_CONNECT: ErrorEvent := eeConnect;<br> 
      <br>
        FD_CLOSE: ErrorEvent := eeDisconnect;<br> 
      <br>
        FD_READ: ErrorEvent := eeReceive;<br> 
      <br>
        FD_WRITE: ErrorEvent := eeSend;<br> 
      <br>
        FD_ACCEPT: ErrorEvent := eeAccept;<br> 
      <br>
      else<br>
      <br>
        ErrorEvent := eeGeneral;<br> 
      <br>
      end;<br>
      <br>
      Error(Self, ErrorEvent, ErrorCode);<br> 
      <br>
      if ErrorCode &lt;> 0 then<br> 
      <br>
        raise ESocketError.CreateResFmt(@sASyncSocketError, [ErrorCode]);<br> 
      <br>
    end else Result := True;<br> 
      <br>
  end;<br>
      <br>
      <br>
      <br>
      begin<br>
      <br>
  with Message do<br> 
      <br>
    if CheckError then<br> 
      <br>
      case SelectEvent of<br> 
      <br>
        FD_CONNECT: Connect(Socket);<br> 
      <br>
        FD_CLOSE: Disconnect(Socket);<br> 
      <br>
        FD_READ: Read(Socket);<br> 
      <br>
        FD_WRITE: Write(Socket);<br> 
      <br>
        FD_ACCEPT: Accept(Socket);//這個很特殊<br> 
      <br>
      end;<br>
      <br>
      end;<br>
      <br>
      呵,又是一個大函數,不過理解起來倒是容易多了,先檢查有沒有錯誤,如果有就調用Error(Self, ErrorEvent, ErrorCode);如果沒有,就根據相應標識,調用相就的函數,其實我們已經可以確定,像Read這些內部一定會調用Event,再由Event調用<br> 
      <br>
      FOnSocketEvent(Self, Socket, SocketEvent);,這樣才能使得ServerSocket這些外部的類獲得事件(上面已經說到它們是怎么把事件關聯起來的了)。<br> 
      <br>
      而源代碼中確實也是這樣的,這里只列出一個read,其他的一樣:<br>
      <br>
      procedure TCustomWinSocket.Read(Socket: TSocket);<br> 
      <br>
      begin<br>
      <br>
  if (FSocket = INVALID_SOCKET) or (Socket &lt;> FSocket) then Exit;<br> 
      <br>
  Event(Self, seRead);<br> 
      <br>
      end;<br>
      <br>
      procedure TCustomWinSocket.Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent);<br> 
      <br>
      begin<br>
      <br>
  if Assigned(FOnSocketEvent) then FOnSocketEvent(Self, Socket, SocketEvent);<br> 
      <br>
      end;<br>
      <br>
      <br>
      <br>
      完了吧,可惜還沒有,回到上面的函數去,發現還有一個方法沒有分析:<br>
      <br>
      FServerSocket.Disconnect(FServerSocket.SocketHandle)可是按我們流程,還不會調用到它,所以這里暫不提它。<br>
      <br>
      <br>
      <br>
      好了,第二步就這樣結束了,再說下去,我自己也暈了。不過我們知道了這一步所完成的任務:連接一個監聽的套接字,并設定好了事件方法指針,在適當的時機會調用適當的事件處理函數。真的得謝謝Delphi為我們做了這么多的事,使我們在使用的時候感覺到是如此的簡單。<br>
      <br>
      <br>
      <br>
      <br>
      <br>
      3.程序執行到這里,得看看ClientSocket吧,有了上面的分析,下面的分析都會簡單得多:<br>
      <br>
      constructor TClientSocket.Create(AOwner: TComponent);<br> 
      <br>
      begin<br>
      <br>
  inherited Create(AOwner);<br> 
      <br>
  FClientSocket := TClientWinSocket.Create(INVALID_SOCKET);<br> 
      <br>
  InitSocket(FClientSocket);<br>
      <br>
      end;<br>
      <br>
      沒有什么值得討論的FClientSocket也是繼承父類的構造方法,上面已經說過了。<br>
      <br>
      接設置Port,Address等,都是到祖先類設置,沒有什么好說的,最后一句是<br>
      <br>
      Active:=true;<br>
      <br>
      上面的討論已經知道,它最后會調用ClientSocket的覆蓋方法:<br>
      <br>
      procedure TClientSocket.DoActivate(Value: Boolean);<br> 
      <br>
      begin<br>
      <br>
  if (Value &lt;> FClientSocket.Connected) and not (csDesigning in ComponentState) then<br> 
      <br>
  begin<br>
      <br>
    if FClientSocket.Connected then<br> 
      <br>
      FClientSocket.Disconnect(FClientSocket.FSocket)<br>
      <br>
    else FClientSocket.Open(FHost, FAddress, FService, FPort, ClientType = ctBlocking);<br> 
      <br>
  end;<br>
      <br>
      end;<br>
      <br>
      這里的Value為True,則調用<br>
      <br>
      FClientSocket.Open(FHost, FAddress, FService, FPort, ClientType = ctBlocking);<br> 
      <br>
      去看看吧:<br>
      <br>
      procedure TCustomWinSocket.Open(const Name, Address, Service: string; Port: Word; Block: Boolean);<br> 
      <br>
      begin<br>
      <br>
  if FConnected then raise ESocketError.CreateRes(@sSocketAlreadyOpen);<br> 
      <br>
  FSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_IP);<br> 
      <br>
  if FSocket = INVALID_SOCKET then raise ESocketError.CreateRes(@sCannotCreateSocket);<br> 
      <br>
  try<br>
      <br>
    Event(Self, seLookUp);<br> 
      <br>
    if Block then<br> 
      <br>
    begin<br>
      <br>
      FAddr := InitSocket(Name, Address, Service, Port, True);<br> 
      <br>
      DoOpen;<br>
      <br>
      &amp;n <br>
    </td>
  </tr>
</table>

</body>

</html>

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲成av人在线观看| 亚洲欧洲制服丝袜| 欧美在线一区二区三区| 91在线精品一区二区| jlzzjlzz国产精品久久| 国产成都精品91一区二区三| 国产一区二区中文字幕| 国产精品1区2区| 国产成人在线视频网址| 成人午夜视频网站| 色综合久久久久综合体| 在线看一区二区| 欧美久久久一区| 亚洲精品在线观| 欧美国产激情二区三区| 亚洲色图在线看| 一区二区激情小说| 舔着乳尖日韩一区| 国内精品久久久久影院薰衣草| 国产毛片一区二区| www.在线欧美| 欧美人狂配大交3d怪物一区| 欧美一级二级三级蜜桃| 国产欧美一区视频| 樱桃视频在线观看一区| 日韩电影在线观看电影| 激情综合五月天| 99久久国产免费看| 日韩免费视频一区| 自拍偷拍国产精品| 久草精品在线观看| 一本色道**综合亚洲精品蜜桃冫| 欧美亚洲综合色| 久久久久久久综合色一本| 18欧美亚洲精品| 人人狠狠综合久久亚洲| 成人高清免费在线播放| 91精品国产综合久久久久久久久久| 精品福利二区三区| 亚洲综合在线免费观看| 狠狠久久亚洲欧美| 欧美体内she精高潮| 中文文精品字幕一区二区| 午夜精品免费在线| 成人免费毛片高清视频| 日韩久久精品一区| 亚洲六月丁香色婷婷综合久久| 毛片av中文字幕一区二区| 色88888久久久久久影院野外| 欧美精品黑人性xxxx| 亚洲精品免费在线| 国产精品1区2区3区| 日韩欧美一级在线播放| 亚洲线精品一区二区三区八戒| 国产美女一区二区三区| 欧美一区二区日韩| 伊人婷婷欧美激情| 成人白浆超碰人人人人| 久久久综合视频| 久久精品国产免费看久久精品| 欧美日韩精品是欧美日韩精品| 国产喷白浆一区二区三区| 激情六月婷婷综合| 日韩欧美卡一卡二| 青娱乐精品视频| 欧美日韩国产一区二区三区地区| 亚洲少妇最新在线视频| 99免费精品视频| 国产精品福利一区| 成人av在线观| 国产精品免费久久久久| 粉嫩一区二区三区性色av| 国产亚洲成年网址在线观看| 国产一区二区福利视频| 久久精品视频在线免费观看| 久久精品久久精品| 久久这里只精品最新地址| 久久99精品久久久久久久久久久久| 91麻豆精品国产综合久久久久久| 丝瓜av网站精品一区二区| 欧美色视频在线| 日韩国产欧美在线观看| 日韩一二三区视频| 国产麻豆日韩欧美久久| 国产精品人妖ts系列视频| k8久久久一区二区三区| 亚洲激情六月丁香| 91精品国产综合久久久久久 | 久久久久久久久岛国免费| 国内精品视频666| 国产精品天干天干在线综合| www.一区二区| 亚洲r级在线视频| 日韩欧美电影一二三| 东方欧美亚洲色图在线| 亚洲丝袜精品丝袜在线| 欧美美女网站色| 久久精品久久久精品美女| 中文一区一区三区高中清不卡| 91蜜桃在线免费视频| 午夜免费久久看| 久久久电影一区二区三区| aa级大片欧美| 日本不卡在线视频| 国产日韩亚洲欧美综合| 欧美三级视频在线| 久久99精品国产.久久久久久| 国产精品成人免费在线| 欧美精品高清视频| 成人亚洲一区二区一| 亚洲成在线观看| 亚洲国产高清在线观看视频| 欧美午夜精品免费| 国产一区欧美一区| 亚洲一区二区在线视频| 2019国产精品| 欧美二区在线观看| 不卡视频免费播放| 狠狠色丁香婷综合久久| 亚洲一区二三区| 欧美国产欧美亚州国产日韩mv天天看完整| 欧美主播一区二区三区| 国产九九视频一区二区三区| 一区二区国产盗摄色噜噜| 欧美国产精品中文字幕| 日韩欧美国产系列| 欧美视频三区在线播放| av不卡免费电影| 国产精品自在欧美一区| 蜜桃av噜噜一区| 亚洲成人福利片| 一区二区三区在线影院| 中文在线免费一区三区高中清不卡| 日韩一区和二区| 欧美精品久久久久久久久老牛影院| 91碰在线视频| 高清不卡一区二区在线| 精品一区二区三区在线观看国产| 亚洲成人精品在线观看| 亚洲综合精品久久| 亚洲精品国产精品乱码不99| 国产亚洲成av人在线观看导航| 欧美一区2区视频在线观看| 欧美中文字幕一二三区视频| av不卡一区二区三区| av一区二区三区四区| 国产精品香蕉一区二区三区| 国产美女精品人人做人人爽| 精东粉嫩av免费一区二区三区| 天堂va蜜桃一区二区三区漫画版| 一区二区三区精品视频| 一区二区三区国产精华| 亚洲狠狠爱一区二区三区| 亚洲国产视频一区| 午夜精品一区二区三区免费视频 | 91麻豆精品国产91久久久使用方法 | 亚洲一区二区三区在线看| 亚洲欧洲韩国日本视频 | 欧美三级日韩三级| 欧美日本韩国一区| 日韩午夜在线观看| 2020国产精品| 国产精品三级av在线播放| 亚洲欧洲成人精品av97| 亚洲精品乱码久久久久久日本蜜臀| 亚洲精品成人天堂一二三| 亚洲国产中文字幕| 另类调教123区| 国产福利一区二区三区视频在线| 风间由美一区二区三区在线观看 | 久久亚洲一级片| 国产精品国产三级国产普通话蜜臀 | 日韩午夜激情av| 欧美mv和日韩mv的网站| 久久精品视频在线看| 亚洲欧美日韩电影| 日本亚洲电影天堂| 粉嫩aⅴ一区二区三区四区五区| 成人国产亚洲欧美成人综合网| 色偷偷88欧美精品久久久| 欧美日韩日日摸| 久久久久久久综合日本| 有码一区二区三区| 精品一区二区在线观看| 色婷婷综合久久| 欧美xxxx在线观看| 亚洲欧美日韩在线播放| 久久精品99国产精品日本| 99精品视频在线播放观看| 欧美一级在线观看| 国产精品久久久久桃色tv| 日韩国产欧美三级| 色偷偷88欧美精品久久久| 欧美mv和日韩mv的网站| 亚洲综合区在线| 成人手机在线视频| 欧美精品一区二区三区蜜臀| 一区二区三区资源| 成人深夜在线观看| 精品久久久三级丝袜|