文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>WinSock学习笔记3:Select模型

WinSock学习笔记3:Select模型

时间:2010-09-28  来源:tc310

WinSock学习笔记3:Select模型

 

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WinSock, ExtCtrls;

type
  TWorkThread = class(TThread)
  private
    FClientSocket: TSocket;
    FMemo: TMemo;
    FBuff: array [0..10] of Char;
    procedure ShowRecv;
  protected
    procedure Execute;override;
  public
    constructor Create(ClientSocket: TSocket; Memo: TMemo);
  end;

  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  ServerSocket: TSocket;
  ClientSocket: TSocket;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  WSData: WSAData;

  LocalAddr: TSockAddrIn;
  SocketMode: Integer;
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:= Inet_addr('127.0.0.1');//点分字符串格式的IP地址转换为互联网格式
  LocalAddr.sin_port:= Htons(1077); //Host To Net Short,主机字节顺序转为网络字节顺序
  //绑定本机IP地址、端口,绑定之前先设置好LocalAddr的参数
  Bind(ServerSocket, LocalAddr, SizeOf(LocalAddr));

  //设置WinSock I/O模式
  SocketMode:= 1;
  IoCtlSocket(ServerSocket, FIONBIO, SocketMode);

  //开始监听,最多同时监听5个连接
  Listen(ServerSocket, 5);
  Timer1.Enabled:= True;
end;

{ TWorkThread }

constructor TWorkThread.Create(ClientSocket: TSocket; Memo: TMemo);
begin
  inherited Create(False);

  FClientSocket:= ClientSocket;
  FMemo:= Memo;
end;

procedure TWorkThread.Execute;
var
  FDSet: TFDSET;
begin
  inherited;

  FreeOnTerminate:= True;

  while not Terminated do
  begin
    FD_Zero(FDSet);       //初始化FDSet
    FD_SET(FClientSocket, FDSet);  //将FClientSocket加入FDSet
    if Select(0, @FDSet, nil, nil, nil) > 0 then  //测试FDSet中是否有可读的连接
    begin
      if Recv(FClientSocket, FBuff, SizeOf(FBuff), 0) > 0 then  //如果收到消息就显示出来
        Synchronize(ShowRecv)
      else
        Break;
    end;
  end;
end;

procedure TWorkThread.ShowRecv;
begin
  FMemo.Lines.Add(FBuff);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  ClientSocket:= Accept(ServerSocket, nil, nil);
  if ClientSocket <> INVALID_SOCKET then
    TWorkThread.Create(ClientSocket, Memo1);
end;

end.

 

 

1.使用Select模型,要定义一个FDSet结构,将客户端Socket加入该结构,用Select函数轮询测试该Socket的读写状态。FDSet结构:

    typedef struct fd_set {
      u_int fd_count;                                     
      SOCKET fd_array[FD_SETSIZE];          
    } fd_set;

2.操作FDSet结构有4个预定义的宏:

       FD_CLR(s, *set)
Removes the descriptor s from set.
       FD_ISSET(s, *set)
Nonzero if s is a member of the set. Otherwise, zero.
       FD_SET(s, *set)
Adds descriptor s to set.
       FD_ZERO(*set)
Initializes the set to the null set.

3.上面的代码为了方便,用了一个Timer来Accept,然后为每一个连接进来的Socket创建线程,在线程中用Select测试是否可读,为使代码简单,没有处理异常的代码。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dropme/archive/2009/09/09/4534748.aspx

相关阅读 更多 +
排行榜 更多 +
泡龙大闯关安卓版

泡龙大闯关安卓版

冒险解谜 下载
割草派对安卓版

割草派对安卓版

飞行射击 下载
堡垒攻防战安卓版

堡垒攻防战安卓版

飞行射击 下载