zoukankan      html  css  js  c++  java
  • Winsock学习笔记5:I/O Overlapped (重叠)模式

    Winsock学习笔记5:I/O Overlapped (重叠)模式

    unit Unit1;

    interface

    uses
      WinSock2, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls;

    type
      TWorkThread 
    = class(TThread)
      
    private
        FMemo: TMemo;
        FBuff: 
    array [0..10of Char;
        FClientSocket: TSocket;
        
    procedure ShowRecv;
      
    protected
        
    procedure Execute;override;
      
    public
        
    constructor Create(Memo: TMemo; ClientSocket: TSocket);
      
    end;

      TForm1 
    = class(TForm)
        Memo1: TMemo;
        Button1: TButton;
        Timer1: TTimer;
        
    procedure Timer1Timer(Sender: TObject);
        
    procedure FormCreate(Sender: TObject);
      
    private
        
    { Private declarations }
      
    public
        
    { Public declarations }
      
    end;

    var
      Form1: TForm1;
      ServerSocket: TSocket;

    implementation

    {$R *.dfm}

    { TWorkThread }

    constructor TWorkThread.Create(Memo: TMemo; ClientSocket: TSocket);
    begin
      
    inherited Create(False);

      FMemo:
    = Memo;
      FClientSocket:
    = ClientSocket;
    end;

    procedure TWorkThread.Execute;
    var
      WSBuff: WSABuf;
      EventTotal: Integer;
      AcceptOverLapped: WSAOverLapped;
      WSAEventArray: 
    array [0..WSA_MAXIMUM_WAIT_EVENTS - 1of WSAEvent;

      Idx: Integer;
      ReceiveBytes: DWORD;
      Flags: DWORD;
      ByteTransferred: DWORD;
    begin
      
    inherited;
      FreeOnTerminate:
    = True;
      EventTotal:
    = 0;

      
    //创建事件
      WSAEventArray[EventTotal]:
    = WSACreateEvent;
      
    //置零
      ZeroMemory(@AcceptOverLapped, SizeOf(WSAOverLapped));
      
    //关联事件
      AcceptOverLapped.hEvent:
    = WSAEventArray[EventTotal];

      WSBuff.len:
    = 22;  //缓冲区的长度要大于客户端发送的长度,如果小于客户端发送长度,会出现乱码
      WSBuff.buf:
    = FBuff;
      Inc(EventTotal);

      
    while not Terminated do
      
    begin
        
    //收消息
        WSARecv(FClientSocket, @WSBuff, EventTotal, ReceiveBytes, Flags, @AcceptOverlapped, 
    nil);
        
    //用WSAWaitForMultipleEvents检测是否有“事件”发生
        Idx:
    = WSAWaitForMultipleEvents(EventTotal, @WSAEventArray[0], False, WSA_INFINITE, False);
        
    //用WSAGetOverlappedResult取得结果
        WSAGetOverlappedResult(FClientSocket, @AcceptOverlapped, @ByteTransferred, False, Flags);
        
    //显示收到的内容
        Synchronize(ShowRecv);

        
    //清零AcceptOverLapped
        ZeroMemory(@AcceptOverLapped, SizeOf(WSAOverLapped));
        
    //关联事件
        AcceptOverLapped.hEvent:
    = WSAEventArray[Idx - WSA_WAIT_EVENT_0];

        
    //重置Event
        WSAResetEvent(WSAEventArray[Idx 
    - WSA_WAIT_EVENT_0]);
      
    end;
    end;

    procedure TWorkThread.ShowRecv;
    begin
      FMemo.Lines.Add(FBuff);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    var
      WSData: TWSAData;
      LocalAddr: TSockaddr;
      SocketMode: Cardinal;
    begin
      
    //初始化Winsock
      WSAStartUp($
    202, WSData);
      
    //创建套接字
      ServerSocket:
    = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      
    //设置LocalAddr的参数
      LocalAddr.sin_family:
    = AF_INET;   //IPV4族
      LocalAddr.sin_addr.S_addr:
    = INADDR_ANY;//这里不能写Inet_addr('127.0.0.1'),负责会绑定失败,不清楚原因是什么;
      LocalAddr.sin_port:
    = Htons(1077); //Host To Net Short,主机字节顺序转为网络字节顺序
      
    //绑定本机IP地址、端口,绑定之前先设置好LocalAddr的参数
      Bind(ServerSocket, @LocalAddr, SizeOf(LocalAddr));

      SocketMode:
    = 1;
      IoCtlSocket(ServerSocket, FIONBIO, SocketMode);

      
    //开始监听
      Listen(ServerSocket, 
    5);
    end;

    procedure TForm1.Timer1Timer(Sender: TObject);
    var
      ClientAddr: TSockAddr;
      ClientAddrLen: Integer;
      ClientSocket: TSocket;
    begin
      
    //接受客户端连接,为对应的客户端创建独立的线程
      ClientAddrLen:
    = SizeOf(ClientAddr);
      ClientSocket:
    = Accept(ServerSocket, ClientAddr, ClientAddrLen);
      
    if ClientSocket <> INVALID_SOCKET then
        TWorkThread.Create(Memo1, ClientSocket);
    end;

    end.

    1.此代码只是为了学习函数的使用方法,为了使代码简单,此处使用Timer管理客户端连接,并为每个连接创建独立的线程,Overlapped的处理方式可在线程的执行部分查看,实际应用中不应该用这种模式;

    2.此代码为消息型的重叠(I/O Overlapped)模式,还有一种“完成例程”模式(非完成端口);

  • 相关阅读:
    sabaki and leelazero
    apply current folder view to all folders
    string operation in powershell
    wirte function in powershell
    add environment path to powershell
    Module in powershell
    sql prompt
    vmware中鼠标在部分区域不能使用
    调整多个控件的dock的顺序
    行为型模型 策略模式
  • 原文地址:https://www.cnblogs.com/tc310/p/1837940.html
Copyright © 2011-2022 走看看