文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Winsock学习笔记5:I/O Overlapped (重叠)模式

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

时间:2010-09-28  来源:tc310

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

相关阅读 更多 +
排行榜 更多 +
泡龙大闯关安卓版

泡龙大闯关安卓版

冒险解谜 下载
割草派对安卓版

割草派对安卓版

飞行射击 下载
堡垒攻防战安卓版

堡垒攻防战安卓版

飞行射击 下载