interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Winsock2, StdCtrls;
type
TfrmMain = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure IOSelectMain;
end;
var
frmMain: TfrmMain;
WSData: TWSAData;
implementation
{$R *.DFM}
{ TfrmMain }
procedure CopyFDSet(Source: TFDSet; var Dest: TFDSet);
var
i: Integer;
begin
FD_ZERO(Dest);
for i:=0 to Source.fd_count - 1 do begin
FD_SET(Source.fd_array[i], Dest);
end;
end;
procedure TfrmMain.IOSelectMain;
var
sListen, sNew: TSocket;
sin, addrRemote: TSockAddrIn;
fdSocket, fdRead: TFDSet;
nRet, nAddrLen, nRecv: Integer;
i: Integer;
sRecv: string;
begin
//创建监听套接字
sListen := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sin.sin_family := AF_INET;
sin.sin_port := htons(4567);
sin.sin_addr.S_addr := INADDR_ANY;
//绑定套接字到本机
if bind(sListen, @sin, SizeOf(sin)) = SOCKET_ERROR then exit;
//进入监听模式
listen(sListen, 5);
//select模型处理过程
//1.初始化一个套接字集合fdSocket, 添加监听套接字句柄到这个集合
FD_ZERO(fdSocket);
FD_SET(sListen, fdSocket);
while true do begin
//2.将fdSocket集合的一个拷贝fdRead传递给select函数
// 当有事件发生时,select函数移除fdRead集合中没有
//未决I/O操作的套接字句柄,然后返回
CopyFDSet(fdSocket, fdRead);
nRet := select(0, @fdRead, nil, nil, nil);
if (nRet>0) then begin
//3.通过将原来fdSocket集合与select处理过的fdRead集合比较
//确定有哪些套接字有未决I/O
for i:=0 to fdSocket.fd_count-1 do begin
if (FD_ISSET(fdSocket.fd_array[i], fdRead)) then begin
if (fdSocket.fd_array[i]=sListen) then begin
//监听套接字接收到新连接
if (fdSocket.fd_count < FD_SETSIZE) then begin
nAddrLen := sizeOf(addrRemote);
sNew := accept(sListen, addrRemote, nAddrLen);
FD_SET(sNew, fdSocket);
ShowMessage(inet_ntoa(addrRemote.sin_addr));
end else begin
Continue;
end;
end else begin
SetLength(sRecv, 1024);
nRecv := recv(fdSocket.fd_array[i], sRecv[1], 1024, 0);
if (nRecv>0) then begin
SetLength(sRecv, nRecv);
ShowMessage(sRecv);
end else begin
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i], fdSocket);
ShowMessage(' Client Quit');
end;
end;
end else begin
end;
end;
end else exit;
end;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
begin
IOSelectMain;
end;
procedure TfrmMain.Button2Click(Sender: TObject);
var
clientSocket: TSocket;
servAddr: TSockAddrIn;
sendstr: string;
begin
clientSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
try
if clientSocket = INVALID_SOCKET then exit;
servAddr.sin_family := AF_INET;
servAddr.sin_port := htons(4567);
servAddr.sin_addr.S_addr := inet_addr('127.0.0.1');
if connect(clientSocket, @servAddr, SizeOf(servAddr)) = -1 then exit;
sendstr := 'test';
send(clientSocket, Pointer(sendstr)^, Length(sendstr), 0);
finally
CloseSocket(clientSocket);
end;
end;
initialization
WSAStartup($0202, WSData);
finalization
WSACleanup;
end.