onlyou13

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1 unit Unit1;  
  2   
  3 interface  
  4   
  5 uses  
  6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7   Dialogs, StdCtrls, WinSock, ExtCtrls;  
  8   
  9 type  
 10   TWorkThread = class(TThread)  
 11   private  
 12     FClientSocket: TSocket;  
 13     FMemo: TMemo;  
 14     FBuff: array [0..10] of Char;  
 15     procedure ShowRecv;  
 16   protected  
 17     procedure Execute;override;  
 18   public  
 19     constructor Create(ClientSocket: TSocket; Memo: TMemo);  
 20   end;  
 21   
 22   TForm1 = class(TForm)  
 23     Memo1: TMemo;  
 24     Button1: TButton;  
 25     Timer1: TTimer;  
 26     procedure Button1Click(Sender: TObject);  
 27     procedure Timer1Timer(Sender: TObject);  
 28   private  
 29     { Private declarations }  
 30   public  
 31     { Public declarations }  
 32   end;  
 33   
 34 var  
 35   Form1: TForm1;  
 36   ServerSocket: TSocket;  
 37   ClientSocket: TSocket;  
 38   
 39 implementation  
 40   
 41 {$R *.dfm}  
 42   
 43 procedure TForm1.Button1Click(Sender: TObject);  
 44 var  
 45   WSData: WSAData;  
 46   
 47   LocalAddr: TSockAddrIn;  
 48   SocketMode: Integer;  
 49 begin  
 50   //初始化Winsock  
 51   WSAStartUp($202, WSData);  
 52   //创建套接字  
 53   ServerSocket:= Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
 54   
 55   //设置LocalAddr的参数  
 56   LocalAddr.sin_family:= AF_INET;   //IPV4族  
 57   LocalAddr.sin_addr.S_addr:= Inet_addr('127.0.0.1');//点分字符串格式的IP地址转换为互联网格式  
 58   LocalAddr.sin_port:= Htons(1077); //Host To Net Short,主机字节顺序转为网络字节顺序  
 59   //绑定本机IP地址、端口,绑定之前先设置好LocalAddr的参数  
 60   Bind(ServerSocket, LocalAddr, SizeOf(LocalAddr));  
 61   
 62   //设置WinSock I/O模式  
 63   SocketMode:= 1;  
 64   IoCtlSocket(ServerSocket, FIONBIO, SocketMode);  
 65   
 66   //开始监听,最多同时监听5个连接  
 67   Listen(ServerSocket, 5);  
 68   Timer1.Enabled:= True;  
 69 end;  
 70   
 71 { TWorkThread }  
 72   
 73 constructor TWorkThread.Create(ClientSocket: TSocket; Memo: TMemo);  
 74 begin  
 75   inherited Create(False);  
 76   
 77   FClientSocket:= ClientSocket;  
 78   FMemo:= Memo;  
 79 end;  
 80   
 81 procedure TWorkThread.Execute;  
 82 var  
 83   FDSet: TFDSET;  
 84 begin  
 85   inherited;  
 86   
 87   FreeOnTerminate:= True;  
 88   
 89   while not Terminated do  
 90   begin  
 91     FD_Zero(FDSet);       //初始化FDSet  
 92     FD_SET(FClientSocket, FDSet);  //将FClientSocket加入FDSet  
 93     if Select(0, @FDSet, nil, nil, nil) > 0 then  //测试FDSet中是否有可读的连接  
 94     begin  
 95       if Recv(FClientSocket, FBuff, SizeOf(FBuff), 0) > 0 then  //如果收到消息就显示出来  
 96         Synchronize(ShowRecv)  
 97       else  
 98         Break;  
 99     end;  
100   end;  
101 end;  
102   
103 procedure TWorkThread.ShowRecv;  
104 begin  
105   FMemo.Lines.Add(FBuff);  
106 end;  
107   
108 procedure TForm1.Timer1Timer(Sender: TObject);  
109 begin  
110   ClientSocket:= Accept(ServerSocket, nil, nil);  
111   if ClientSocket <> INVALID_SOCKET then  
112     TWorkThread.Create(ClientSocket, Memo1);  
113 end;  
114   
115 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测试是否可读,为使代码简单,没有处理异常的代码。

本文转载自http://blog.csdn.net/dropme/article/details/4534748

posted on 2013-11-14 20:38  onlyou13  阅读(115)  评论(0编辑  收藏  举报