学习笔记:delphi实现网络通信之select模型
2011-04-28 15:18
393 查看
说明:所有的winsock的定义用的是jwawinsock2。(整个包的下载:http://blog.delphi-jedi.net/home/)
主要函数:select
目的:允许那些想要避免在套接字调用上阻塞的应用程序有能力管理多个套接字。
函数定义:select(nfds:integer;readfds:Pfd_set;writefds:Pfd_set;exceptfds:Pfd_set;timeout:Ptimeval)
套接集合:FD_SET结构
PFD_SET=^Fd_set
Fd_set=record
fd_count:integer;
fd_array:array[0..FD_SETSIZE-1] of Tsocket;
end;{FD_SETSIZE系统默认为64.也就是系统默认管理64个套接字。实际可以定义到1000。}
关于FD_SET集合操作函数。
FD_ZERO(SET:PFD_SET) 初始化set为空集合。集合在使用前应该总是清空。
FD_CLR(s:TSOCKET;set:PFD_SET) 从set移除套接字。
FD_ISSETs(S:TSOCKET;SET:PFD_SET) 检查s是不是set的成员,如果是返回TRUE。
FD_SET(S:TSOCKET;set:PFD_SET)添加套接字到集合。
delphi代码:
program Proserver;
//控制台程序。
{$APPTYPE CONSOLE}
uses
JwaWinsock2,Windows,SysUtils;
var
nPort:UINT;
sListen,sNew:TSocket;
socket_in,addrRemote:sockaddr_in;
fdSocket,fdRead:fd_set;
i,nAddrLen:integer;
szText:array[0..255] of AnsiChar;
procedure initsock;
var
v_wsadata:WSAData;
sockversion:Cardinal;
begin
sockversion:=MAKEWORD(2,2);
try
if WSAStartup(sockversion,v_wsadata)<>0 then
Exit;
except
Exit;
end;
end;
procedure cleansock;
begin
WSACleanup();
end;
begin
initsock;
nport:=4567;
sListen:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
socket_in.sin_family:=AF_INET;
socket_in.sin_port:=htons(nPort);
socket_in.sin_addr.S_addr:=INADDR_ANY;
//进行SOCKET绑定到本地机器
if bind(sListen,psockaddr(@socket_in),SizeOf(socket_in))=socket_error then
begin
writeln('Failed bind()');
Exit;
end
else
begin
Writeln('SOCKET绑定成功。');
end;
//进入监听模式
Writeln('程序进入监听状态......');
listen(sListen,5);
//select模型处理过程
//1、初始化一个套接字集合fdsocket,添加监听套接字句柄到这个集合。
FD_ZERO(fdSocket);
_FD_SET(sListen,fdSocket);
//进行等待状态中。。。。。。
Writeln('进入无限循环状态。。。。。');
while True do
begin
// 2、将FDSOCKET集合的一个拷贝FDREAD传递给SELECT函数。
fdRead:=fdSocket;
if select(0,@fdread,nil,nil,nil)>0 then
begin
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,psockaddr(@addrRemote),@nAddrlen);
_FD_SET(sNew,fdSocket);
Writeln('接收到连接:'+strpas(inet_ntoa(addrRemote.sin_addr)));
end
else
begin
Writeln('连接太多,超出系统要求。');
Continue;
end;
end
else
begin
if recv(fdSocket.fd_array[i],szText,SizeOf(szText),0)>0 then
begin
Writeln('接收的数据是:'+strpas(sztext));
end
else
begin
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i],fdSocket);
Writeln('当前连接已判断。');
end;
end;
end;
end;
end
else
begin
Writeln('Failed select().');
Break;
end;
end;
cleansock;
end.
主要函数:select
目的:允许那些想要避免在套接字调用上阻塞的应用程序有能力管理多个套接字。
函数定义:select(nfds:integer;readfds:Pfd_set;writefds:Pfd_set;exceptfds:Pfd_set;timeout:Ptimeval)
套接集合:FD_SET结构
PFD_SET=^Fd_set
Fd_set=record
fd_count:integer;
fd_array:array[0..FD_SETSIZE-1] of Tsocket;
end;{FD_SETSIZE系统默认为64.也就是系统默认管理64个套接字。实际可以定义到1000。}
关于FD_SET集合操作函数。
FD_ZERO(SET:PFD_SET) 初始化set为空集合。集合在使用前应该总是清空。
FD_CLR(s:TSOCKET;set:PFD_SET) 从set移除套接字。
FD_ISSETs(S:TSOCKET;SET:PFD_SET) 检查s是不是set的成员,如果是返回TRUE。
FD_SET(S:TSOCKET;set:PFD_SET)添加套接字到集合。
delphi代码:
program Proserver;
//控制台程序。
{$APPTYPE CONSOLE}
uses
JwaWinsock2,Windows,SysUtils;
var
nPort:UINT;
sListen,sNew:TSocket;
socket_in,addrRemote:sockaddr_in;
fdSocket,fdRead:fd_set;
i,nAddrLen:integer;
szText:array[0..255] of AnsiChar;
procedure initsock;
var
v_wsadata:WSAData;
sockversion:Cardinal;
begin
sockversion:=MAKEWORD(2,2);
try
if WSAStartup(sockversion,v_wsadata)<>0 then
Exit;
except
Exit;
end;
end;
procedure cleansock;
begin
WSACleanup();
end;
begin
initsock;
nport:=4567;
sListen:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
socket_in.sin_family:=AF_INET;
socket_in.sin_port:=htons(nPort);
socket_in.sin_addr.S_addr:=INADDR_ANY;
//进行SOCKET绑定到本地机器
if bind(sListen,psockaddr(@socket_in),SizeOf(socket_in))=socket_error then
begin
writeln('Failed bind()');
Exit;
end
else
begin
Writeln('SOCKET绑定成功。');
end;
//进入监听模式
Writeln('程序进入监听状态......');
listen(sListen,5);
//select模型处理过程
//1、初始化一个套接字集合fdsocket,添加监听套接字句柄到这个集合。
FD_ZERO(fdSocket);
_FD_SET(sListen,fdSocket);
//进行等待状态中。。。。。。
Writeln('进入无限循环状态。。。。。');
while True do
begin
// 2、将FDSOCKET集合的一个拷贝FDREAD传递给SELECT函数。
fdRead:=fdSocket;
if select(0,@fdread,nil,nil,nil)>0 then
begin
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,psockaddr(@addrRemote),@nAddrlen);
_FD_SET(sNew,fdSocket);
Writeln('接收到连接:'+strpas(inet_ntoa(addrRemote.sin_addr)));
end
else
begin
Writeln('连接太多,超出系统要求。');
Continue;
end;
end
else
begin
if recv(fdSocket.fd_array[i],szText,SizeOf(szText),0)>0 then
begin
Writeln('接收的数据是:'+strpas(sztext));
end
else
begin
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i],fdSocket);
Writeln('当前连接已判断。');
end;
end;
end;
end;
end
else
begin
Writeln('Failed select().');
Break;
end;
end;
cleansock;
end.
相关文章推荐
- Linux网络编程select模型的实现
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Epoll模型
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——朴素模型
- 从零实现一个最精简的select网络服务模型
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较
- Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll、Epoll模型处理长连接性能比较
- Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)
- 电子书下载:Delphi 网络通信协议分析与应用实现
- socket通信网络模型 ——Epoll、IOCP模型详解以及与select、kqueue等常见模型的区别特点
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Select模型
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll模型
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Epoll模型
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较
- WSAEventSelect模型基于TCP协议的控制台网络通信程序
- 使用socket实现基于select模型的网络聊天室
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll、Epoll模型处理长连接性能比较
- 用select实现1对多的网络通信,多线程实现,且可以实现退出,相互间对话消息不受干扰