本示例中,涉及到的缓冲,均采取1024长度,采用的select轮询,现在select轮询已经被认为是比较低级的方法了,微软也不推荐使用,这里就以它开头吧,有时间,大家可以研究其他用法,比如WSAAsyncSelect模型 ,WSAEventSelect模型 ,Overlapped I/O 事件通知模型 ,Overlapped I/O 完成例程模型 ,IOCP模型 。下面开始贴代码了:
服务端单元:SocketServer
- unit SocketServer;
- interface
- uses
- Windows, Classes,SyncObjs ,WinSock ,SysUtils;
- type
- TGetDataEvent = procedure(const stream:TMemoryStream) of object;
- TClientConnected = procedure(const socket: TSocket) of object;
- TWorkThread = class;
- TServerItem = class;
- TSocketServer = class
- private
- FServerSocket : TSocket;
- //客户端连接列表
- FClientSocketList : TStringList;
- FServerItem : TServerItem;
- //允许最大连接数
- FMaxClientCount : Integer;
- //客户端连接数
- FClientCount : Integer;
- //当前客户端的索引
- FClientIndex : Integer;
- //调用方的Handle
- FCallHandle : HWND;
- //接收用的内存流
- FRecStream : TMemoryStream;
- //接收缓冲区
- FRecBuf : array of byte;
- FHost : AnsiString;
- FPort : Integer;
- FTimeVal: TTimeVal;
- //工作线程
- FWorkThread : TWorkThread;
- //以下是自定义事件
- FOnGetData : TGetDataEvent;
- FOnClientConnected : TClientConnected;
- //初始化套接字
- function InitSocket:Boolean;
- //从某个客户端套接字中获取数据
- procedure GetDataFromClient(socket:TSocket);
- //检查是否有新的客户端连接
- procedure CheckNewSocket;
- procedure SetMaxClientCount(const Value:Integer);
- function GetMaxClientCount:Integer;
- function GetClientCount:Integer;
- function GetMaxClient: Integer;
- procedure SetMaxClient(const Value: Integer);
- protected
- procedure DoRevData(stream:TMemoryStream);
- procedure DoClientConnected(socket:TSocket);
- //取得某个套接字的IP地址
- function GetItemIP(index:Integer):PAnsiChar;
- function GetItemActived(index:Integer):Boolean;
- procedure SetItemActived(index:Integer;const Value:Boolean);
- public
- //ACallHandle:调用者的句柄, CreateSuspended:线程是否挂起
- constructor Create(ACallHandle:HWND;CreateSuspended: Boolean);overload;
- //启用监听
- function ListenStart:Boolean;
- //执行线程
- procedure ResumeThread;
- property Host : AnsiString read FHost write FHost;
- property Port : Integer read FPort write FPort;
- property MaxClientCount : Integer read GetMaxClientCount write SetMaxClientCount;
- property OnClientConnected : TClientConnected read FOnClientConnected write FOnClientConnected;
- property OnGetData : TGetDataEvent read FOnGetData write FOnGetData;
- property ClientSocketList : TStringList read FClientSocketList;
- property IP[index: Integer] : PAnsiChar read GetItemIP;
- property ItemActived[index: Integer] : Boolean read GetItemActived write SetItemActived;
- property ClientCount : Integer read GetClientCount write FClientCount;
- property ClientIndex : Integer read FClientIndex;
- end;
- TWorkThread = class(TThread)
- private
- //临界
- FLock : TCriticalSection;
- FSocketServer : TSocketServer;
- procedure Execute;override;
- procedure ReciveFromClient;
- public
- constructor Create(ASocketServer:TSocketServer;CreateSuspended: Boolean);overload;
- end;
- TServerItem = class
- private
- FSocket : TSocket;
- FIP : PAnsiChar;
- FActived : Boolean;
- public
- property Socket : TSocket read FSocket write FSocket;
- property IP : PAnsiChar read FIP write FIP;
- property Actived : Boolean read FActived w