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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值