1 unit Unit1; 2 3 interface 4 5 uses 6 WinSock2, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 7 Dialogs, StdCtrls, ExtCtrls; 8 9 type 10 TWorkThread = class(TThread) 11 private 12 FMemo: TMemo; 13 FBuff: array [0..10] of Char; 14 FClientSocket: TSocket; 15 procedure ShowRecv; 16 protected 17 procedure Execute;override; 18 public 19 constructor Create(Memo: TMemo; ClientSocket: TSocket); 20 end; 21 22 TForm1 = class(TForm) 23 Memo1: TMemo; 24 Button1: TButton; 25 Timer1: TTimer; 26 procedure Timer1Timer(Sender: TObject); 27 procedure FormCreate(Sender: TObject); 28 private 29 { Private declarations } 30 public 31 { Public declarations } 32 end; 33 34 var 35 Form1: TForm1; 36 ServerSocket: TSocket; 37 38 implementation 39 40 {$R *.dfm} 41 42 { TWorkThread } 43 44 constructor TWorkThread.Create(Memo: TMemo; ClientSocket: TSocket); 45 begin 46 inherited Create(False); 47 48 FMemo:= Memo; 49 FClientSocket:= ClientSocket; 50 end; 51 52 procedure TWorkThread.Execute; 53 var 54 WSBuff: WSABuf; 55 EventTotal: Integer; 56 AcceptOverLapped: WSAOverLapped; 57 WSAEventArray: array [0..WSA_MAXIMUM_WAIT_EVENTS - 1] of WSAEvent; 58 59 Idx: Integer; 60 ReceiveBytes: DWORD; 61 Flags: DWORD; 62 ByteTransferred: DWORD; 63 begin 64 inherited; 65 FreeOnTerminate:= True; 66 EventTotal:= 0; 67 68 //创建事件 69 WSAEventArray[EventTotal]:= WSACreateEvent; 70 //置零 71 ZeroMemory(@AcceptOverLapped, SizeOf(WSAOverLapped)); 72 //关联事件 73 AcceptOverLapped.hEvent:= WSAEventArray[EventTotal]; 74 75 WSBuff.len:= 22; //缓冲区的长度要大于客户端发送的长度,如果小于客户端发送长度,会出现乱码 76 WSBuff.buf:= FBuff; 77 Inc(EventTotal); 78 79 while not Terminated do 80 begin 81 //收消息 82 WSARecv(FClientSocket, @WSBuff, EventTotal, ReceiveBytes, Flags, @AcceptOverlapped, nil); 83 //用WSAWaitForMultipleEvents检测是否有“事件”发生 84 Idx:= WSAWaitForMultipleEvents(EventTotal, @WSAEventArray[0], False, WSA_INFINITE, False); 85 //用WSAGetOverlappedResult取得结果 86 WSAGetOverlappedResult(FClientSocket, @AcceptOverlapped, @ByteTransferred, False, Flags); 87 //显示收到的内容 88 Synchronize(ShowRecv); 89 90 //清零AcceptOverLapped 91 ZeroMemory(@AcceptOverLapped, SizeOf(WSAOverLapped)); 92 //关联事件 93 AcceptOverLapped.hEvent:= WSAEventArray[Idx - WSA_WAIT_EVENT_0]; 94 95 //重置Event 96 WSAResetEvent(WSAEventArray[Idx - WSA_WAIT_EVENT_0]); 97 end; 98 end; 99 100 procedure TWorkThread.ShowRecv; 101 begin 102 FMemo.Lines.Add(FBuff); 103 end; 104 105 procedure TForm1.FormCreate(Sender: TObject); 106 var 107 WSData: TWSAData; 108 LocalAddr: TSockaddr; 109 SocketMode: Cardinal; 110 begin 111 //初始化Winsock 112 WSAStartUp($202, WSData); 113 //创建套接字 114 ServerSocket:= Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 115 //设置LocalAddr的参数 116 LocalAddr.sin_family:= AF_INET; //IPV4族 117 LocalAddr.sin_addr.S_addr:= INADDR_ANY;//这里不能写Inet_addr('127.0.0.1'),负责会绑定失败,不清楚原因是什么; 118 LocalAddr.sin_port:= Htons(1077); //Host To Net Short,主机字节顺序转为网络字节顺序 119 //绑定本机IP地址、端口,绑定之前先设置好LocalAddr的参数 120 Bind(ServerSocket, @LocalAddr, SizeOf(LocalAddr)); 121 122 SocketMode:= 1; 123 IoCtlSocket(ServerSocket, FIONBIO, SocketMode); 124 125 //开始监听 126 Listen(ServerSocket, 5); 127 end; 128 129 procedure TForm1.Timer1Timer(Sender: TObject); 130 var 131 ClientAddr: TSockAddr; 132 ClientAddrLen: Integer; 133 ClientSocket: TSocket; 134 begin 135 //接受客户端连接,为对应的客户端创建独立的线程 136 ClientAddrLen:= SizeOf(ClientAddr); 137 ClientSocket:= Accept(ServerSocket, ClientAddr, ClientAddrLen); 138 if ClientSocket <> INVALID_SOCKET then 139 TWorkThread.Create(Memo1, ClientSocket); 140 end; 141 142 end.
1.此代码只是为了学习函数的使用方法,为了使代码简单,此处使用Timer管理客户端连接,并为每个连接创建独立的线程,Overlapped的处理方式可在线程的执行部分查看,实际应用中不应该用这种模式
2.此代码为消息型的重叠(I/O Overlapped)模式,还有一种“完成例程”模式(非完成端口)