Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16496425
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 20:50:21

下载本文示例代码
  老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系。他们的信会被邮递员投递到他们的信箱里。  这和Socket模型非常类似。下面我就以老陈接收信件为例讲解Socket I/O模型。  一:select模型  老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱,看是否有女儿的信,在这种情况下,“下楼检查信箱”然后回到楼上耽误了老陈太多的时间,以至于老陈无法做其他工作。  select模型和老陈的这种情况非常相似:周而复始地去检查......如果有数据......接收/发送.......  使用线程来select应该是通用的做法: procedure TListenThread.Execute;var addr : TSockAddrIn; fd_read : TFDSet; timeout : TTimeVal; ASock, MainSock : TSocket; len, i : Integer;begin MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); addr.sin_family := AF_INET; addr.sin_port := htons(5678); addr.sin_addr.S_addr := htonl(INADDR_ANY); bind( MainSock, @addr, sizeof(addr) ); listen( MainSock, 5 ); while (not Terminated) do begin  FD_ZERO( fd_read );  FD_SET( MainSock, fd_read );  timeout.tv_sec := 0;  timeout.tv_usec := 500;  if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //至少有1个等待Accept的connection  begin   if FD_ISSET( MainSock, fd_read ) then   begin   for i:=0 to fd_read.fd_count-1 do //注意,fd_count <= 64,也就是说select只能同时管理最多64个连接   begin    len := sizeof(addr);    ASock := accept( MainSock, addr, len );    if ASock <> INVALID_SOCKET then     ....//为ASock创建一个新的线程,在新的线程中再不停地select    end;    end;     end;  end; //while (not self.Terminated) shutdown( MainSock, SD_BOTH ); closesocket( MainSock );end;  二:WSAAsyncSelect模型  后来,老陈使用了微软公司的新式信箱。这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了,牙也不疼了,你瞅准了,蓝天......不是,微软......  微软提供的WSAAsyncSelect模型就是这个意思。  WSAAsyncSelect模型是Windows下最简单易用的一种Socket I/O模型。使用这种模型时,Windows会把网络事件以消息的形势通知应用程序。  首先定义一个消息标示常量: const WM_SOCKET = WM_USER 55;  再在主Form的private域添加一个处理此消息的函数声明: privateprocedure WMSocket(var Msg: TMessage); message WM_SOCKET;  然后就可以使用WSAAsyncSelect了: var addr : TSockAddr; sock : TSocket; sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); addr.sin_family := AF_INET; addr.sin_port := htons(5678); addr.sin_addr.S_addr := htonl(INADDR_ANY); bind( m_sock, @addr, sizeof(SOCKADDR) ); WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE ); listen( m_sock, 5 ); ....  应用程序可以对收到WM_SOCKET消息进行分析,判断是哪一个socket产生了网络事件以及事件类型: procedure TfmMain.WMSocket(var Msg: TMessage);var sock : TSocket; addr : TSockAddrIn; addrlen : Integer; buf : Array [0..4095] of Char;begin //Msg的WParam是产生了网络事件的socket句柄,LParam则包含了事件类型 case WSAGetSelectEvent( Msg.LParam ) of FD_ACCEPT :  begin   addrlen := sizeof(addr);   sock := accept( Msg.WParam, addr, addrlen );   if sock <> INVALID_SOCKET then    WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE );  end;  FD_CLOSE : closesocket( Msg.WParam );  FD_READ : recv( Msg.WParam, buf[0], 4096, 0 );  FD_WRITE : ; end; end;共3页。 1 2 3 :   老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系。他们的信会被邮递员投递到他们的信箱里。  这和Socket模型非常类似。下面我就以老陈接收信件为例讲解Socket I/O模型。  一:select模型  老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱,看是否有女儿的信,在这种情况下,“下楼检查信箱”然后回到楼上耽误了老陈太多的时间,以至于老陈无法做其他工作。  select模型和老陈的这种情况非常相似:周而复始地去检查......如果有数据......接收/发送.......  使用线程来select应该是通用的做法: procedure TListenThread.Execute;var addr : TSockAddrIn; fd_read : TFDSet; timeout : TTimeVal; ASock, MainSock : TSocket; len, i : Integer;begin MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); addr.sin_family := AF_INET; addr.sin_port := htons(5678); addr.sin_addr.S_addr := htonl(INADDR_ANY); bind( MainSock, @addr, sizeof(addr) ); listen( MainSock, 5 ); while (not Terminated) do begin  FD_ZERO( fd_read );  FD_SET( MainSock, fd_read );  timeout.tv_sec := 0;  timeout.tv_usec := 500;  if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //至少有1个等待Accept的connection  begin   if FD_ISSET( MainSock, fd_read ) then   begin   for i:=0 to fd_read.fd_count-1 do //注意,fd_count <= 64,也就是说select只能同时管理最多64个连接   begin    len := sizeof(addr);    ASock := accept( MainSock, addr, len );    if ASock <> INVALID_SOCKET then     ....//为ASock创建一个新的线程,在新的线程中再不停地select    end;    end;     end;  end; //while (not self.Terminated) shutdown( MainSock, SD_BOTH ); closesocket( MainSock );end;  二:WSAAsyncSelect模型  后来,老陈使用了微软公司的新式信箱。这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了,牙也不疼了,你瞅准了,蓝天......不是,微软......  微软提供的WSAAsyncSelect模型就是这个意思。  WSAAsyncSelect模型是Windows下最简单易用的一种Socket I/O模型。使用这种模型时,Windows会把网络事件以消息的形势通知应用程序。  首先定义一个消息标示常量: const WM_SOCKET = WM_USER 55;  再在主Form的private域添加一个处理此消息的函数声明: privateprocedure WMSocket(var Msg: TMessage); message WM_SOCKET;  然后就可以使用WSAAsyncSelect了: var addr : TSockAddr; sock : TSocket; sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); addr.sin_family := AF_INET; addr.sin_port := htons(5678); addr.sin_addr.S_addr := htonl(INADDR_ANY); bind( m_sock, @addr, sizeof(SOCKADDR) ); WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE ); listen( m_sock, 5 ); ....  应用程序可以对收到WM_SOCKET消息进行分析,判断是哪一个socket产生了网络事件以及事件类型: procedure TfmMain.WMSocket(var Msg: TMessage);var sock : TSocket; addr : TSockAddrIn; addrlen : Integer; buf : Array [0..4095] of Char;begin //Msg的WParam是产生了网络事件的socket句柄,LParam则包含了事件类型 case WSAGetSelectEvent( Msg.LParam ) of FD_ACCEPT :  begin   addrlen := sizeof(addr);   sock := accept( Msg.WParam, addr, addrlen );   if sock <> INVALID_SOCKET then    WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE );  end;  FD_CLOSE : closesocket( Msg.WParam );  FD_READ : recv( Msg.WParam, buf[0], 4096, 0 );  FD_WRITE : ; end; end;共3页。 1 2 3 : 下载本文示例代码


基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触基于Delphi的Socket I/O模型全接触
阅读(190) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~