• 学习笔记之WSAAsyncSelect模式


    大体原理:WSAAsyncSelect模式允许以windows消息的形式接收网络事件通知。这个模式是为了适应windows消息驱动环境而设置的,对性能要求不高的网络应用程序可采用此模式。

    要注意的地方:网络事件消息抵达消息处理函数后,应用程序首先检查Lparam参数的高位,以判断在套接字上发生了网络错误。宏WSAGETSELECTERROR返回高字节包含的错误信息。若应用程序发现套接字上没有产生任何错误便可用宏WSAGETSELECTEVENT读取LPARAM参数的低字位确定发生的网络事件。

    优缺点:WSAAsyncSelect模型最突出的特点是与windows的消息驱动机制融在了一起,这使得开发带GUI界面的网络程序变得很简单。但是如果连接增加,单个WINDOWS函数处理上千个客户请求时,服务器性能势必发受到影响。

    主要函数:WSAAsyncSelect。

    主要参数:发送的通知码含义:

    FD_READ:套接字接收到对方发送过来的数据包,表明可以去读套接字了。

    FD_WRITE: 数据缓冲区满后再次变空时,通知应用 程序可以继续发送数据了。

               注:send函数先将要发送的数据放入缓冲区中后,由windows负责将数据发送出去。如果缓冲区满了, 则不能发送数据了。当FD_WRITE后,可以再发送数据。

    FD_ACCEPT,FD_CONNECT,FD_CLOSE。看单词就明白了。

    DELPHI代码:

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,JwaWinsock2;
    const
      WM_SOCKET=WM_USER+100;
    type
      TForm1 = class(TForm)
        mmo1: TMemo;
        btn1: TButton;
        mmo2: TMemo;
        btn2: TButton;
        procedure FormCreate(Sender: TObject);
        procedure btn1Click(Sender: TObject);
        procedure btn2Click(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        procedure Self_WndProc(var Msg: TMessage);  //拦截窗体的所有消息
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;
      Oldwindowproc:TWndMethod;
      sListen:TSocket;
      WSData: TWSAData;
    implementation

    {$R *.dfm}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      OldWindowProc   := Self.WindowProc; //保存原来的函数地址;
      Self.WindowProc :=Self_WndProc;     //指定新的函数地址;
      WSAStartup($0202, WSData);
      sListen:=INVALID_SOCKET;
      sListen:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    end;
    procedure TForm1.Self_WndProc(var msg:TMessage);
    var
      sClient, sEvent: TSocket;
      addrRemote: TSockAddrIn;
      addrlen:Integer;
      szText:array[0..255] of AnsiChar;
    begin
      if Msg.Msg=WM_SOCKET then
        begin
          sEvent:=Msg.WParam;
          if WSAGETASYNCERROR(Msg.LParam)<>0 then
            begin
              closesocket(sEvent);
            end
          else
            begin
              case WSAGETSELECTEVENT(Msg.LParam) of
                FD_ACCEPT:  //当监听到套接字有连接进入时。
                  begin
                    addrlen:=SizeOf(addrRemote);
                    sClient:=accept(sEvent,psockaddr(@addrRemote),@addrlen);
                    WSAAsyncSelect(sClient,Self.Handle,WM_SOCKET,FD_ACCEPT or FD_CLOSE or FD_READ or FD_WRITE);
                    mmo1.Lines.Add('当前连接IP信息:'+strpas(inet_ntoa(addrRemote.sin_addr)));
                  end;
                FD_WRITE:
                  begin

                  end;
                FD_READ:
                  begin
                    if recv(sEvent,szText,SizeOf(szText),0)>0 then
                         begin
                           mmo2.Lines.Add('接收的数据是:'+strpas(sztext));
                         end
                       else
                         begin
                           closesocket(sEvent);
                         end;
                  end;
                FD_CLOSE:
                   begin
                     closesocket(sEvent);
                     mmo1.Lines.Add('用户断开连接。');
                   end;
              end;
            end;
        end;
       OldWindowProc(Msg);
    end;
    procedure TForm1.btn1Click(Sender: TObject);    //启动临听服务
    var
      sins:sockaddr_in;
    begin
     if sListen<>INVALID_SOCKET then
       begin
         Sins.sin_family  :=AF_INET;
         sins.sin_port    :=htons(4567);
         sins.sin_addr.S_addr:=INADDR_ANY;
         if bind(sListen,@sins,SizeOf(sins))=SOCKET_ERROR then
          begin
             ShowMessage('无法进行端口绑定。');
             Exit;
          end;
         WSAAsyncSelect(sListen,Self.Handle,WM_SOCKET,FD_ACCEPT or FD_CLOSE or FD_READ or FD_WRITE);
         listen(sListen,5);
         btn1.Enabled:=False;
       end;

  • 相关阅读:
    selenium-java,定位并操作frame和iframe内的元素
    多线程-java
    Mysql基础
    webpack文件处理
    webpack调试必备配置之SourceMap介绍
    webpack提取分离css单独打包
    webpack编译less和sass
    webpack中loader在处理HTML中引入图片
    webpack用loader加载css
    使用配置文件webpack.config.js打包文件
  • 原文地址:https://www.cnblogs.com/wangorg/p/2032996.html
Copyright © 2020-2023  润新知