• 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)模式,还有一种“完成例程”模式(非完成端口);

  • 相关阅读:
    JAVA-JDBC
    如何优雅地拼SQL的in子句
    Groovy 语言尝鲜
    小而美的CNC机器
    GCode软件和资料
    基于PC的运动控制
    CAD/CAM软件
    工控硬件
    数控系统
    Visual Studio 2019 Community 版离线注册
  • 原文地址:https://www.cnblogs.com/tc310/p/1837940.html
Copyright © 2020-2023  润新知