博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习笔记之WSAAsyncSelect模式
阅读量:5140 次
发布时间:2019-06-13

本文共 2902 字,大约阅读时间需要 9 分钟。

大体原理: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;

转载于:https://www.cnblogs.com/wangorg/archive/2011/04/29/2032996.html

你可能感兴趣的文章
幸运转盘v1.0 【附视频】我的Android原创处女作,请支持!
查看>>
安装 Express
查看>>
存储(硬件方面的一些基本术语)
查看>>
Weka中数据挖掘与机器学习系列之基本概念(三)
查看>>
leetcode-Sort List
查看>>
中文词频统计
查看>>
Java泛型的基本使用
查看>>
bzoj2038 [2009国家集训队]小Z的袜子(hose)
查看>>
Postman-----如何导入和导出
查看>>
【Linux】ping命令详解
查看>>
8、RDD持久化
查看>>
第二次团队冲刺--2
查看>>
[转载]加密算法库Crypto——nodejs中间件系列
查看>>
使用Xshell密钥认证机制远程登录Linux
查看>>
【模板】最小生成树
查看>>
java面试题
查看>>
pair的例子
查看>>
uva 387 A Puzzling Problem (回溯)
查看>>
Oracle中包的创建
查看>>
django高级应用(分页功能)
查看>>