如题,先谢谢了
解决方案 »
- 银行系统中金额字段一般都用什么oracle数据类型
- 关于一个string里的字符换行问题
- fastreport问题,急需解决!!如何在主项数据中指定2个数据集,横向显示两个数据集的数据?up有分
- String如何转换成PChar?
- 急(在线等待)
- 如何把用foxpro2.6写的数据库dbf导入到sqlserver2000中?
- @@@@@@@@@各位大哥 谁有进销存的软件代码 我急需 要多少分都给@@@@@@@@@
- 关于网络软件设计的问题,请帮忙回答!
- 如何消除图片切换时的画面闪烁现象?
- 学了一辈子的Delphi,居然连最基本的Windows程序结构也不懂
- 从右到左动态生成控件,左边超过界面不显示滚动条,怎么解决??/?谢谢!!!!!!!!!
- 求一个socketconnection三层的例子
调用方法 listen 开始侦听,最后用一个 while 循环阻塞调用 accept 函数用于等待来自 client 端的连接,如果这个 socket 在主线程(主程序)中运行,这将导致主线程的阻塞。因此,需要创建一个新的线程以运行 socket 服务。server 端与 client 端之间的通信处于同步状态下。 非阻塞模式
利用 socket 事件 的消息机制, server 端与 client 端之间的通信处于异步状态下。 创建一个socket时,可以指定它是否阻塞。在缺省情况下,Socket函数和WinSock都创建“阻塞”的socket。阻塞socket通过使用select函数或者WSAAsynSelect函数在指定操作下变成非阻塞的。假定应用程序的一个socket s指定了监测FD_READ事件,则在FD_READ事件上变成非阻塞的。当read函数被调用时,不管是否读到数据都马上返回,如果返回一个错误信息表示还在等待,则在等待的数据到达后,消息wMsg发送给窗口hWnd,应用程序处理该消息读取网络数据。
procedure TForm1.Button1Click(Sender: TObject);
var
FdSet : TFDSet;
TimeVal : TTimeVal;
ErrorCode,AddSize : integer;
SockAdd_In,Add: TSockAddrIn;
tm : Longint;
WSAData : TWSAData;
FSock,AcceptSock : TSocket;
begin
FSock := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if FSock = SOCKET_ERROR then
begin
showmessage(Format('%s;ErrorCode:%d',['套接字创建失败',WSAGetLastError]) );
Exit;
end;
if ckbxB.Checked then
tm := 1 //非锁定模式
else tm := 0; //锁定模式
ioctlsocket(FSock,FIONBIO,tm);SockAdd_In.sin_family := PF_INET;
SockAdd_In.sin_port := htons(5151);
SockAdd_In.sin_addr.S_addr := htonl(INADDR_ANY);
//绑定
ErrorCode := bind(FSock,SockAdd_In,sizeof(SockAdd_In));
if ErrorCode = SOCKET_ERROR then
begin
showmessage(Format('%s;ErrorCode:%d',['绑定失败:',WSAGetLastError]) );
Exit;
end;
//置为监听模式
listen(FSock,5);
//用一个循环来反复判断是否有客户端请求,如果存在请求就创建一个用来接受数据的读取线程
while true do
begin
AddSize := sizeof(Add);
AcceptSock := accept(FSock,@Add,@AddSize);
if AcceptSock <> INVALID_SOCKET then
TSockReadThread.Create(AcceptSock,Memo1);
Application.ProcessMessages;
end;
//上面的是阻塞模式
如果将循环改成这样,那就是非阻塞模式
while true do
begin
FD_ZERO(FdSet);
FD_SET(FSock,FdSet);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 500;
//使用select函数
if (select(0,@fdSet,nil,nil,@TimeVal) > 0) then
begin
AddSize := sizeof(Add);
AcceptSock := accept(FSock,@Add,@AddSize);
if AcceptSock <> INVALID_SOCKET then
TSockReadThread.Create(AcceptSock,Memo1);
end;
Application.ProcessMessages; end;
end;
随便解释一下
timeval = record
tv_sec: Longint;
tv_usec: Longint;
end;
其中,tv_sec字段以秒为单位指定等待时间;tv_usec字段则以毫秒为单位指定等待时间。若将超时值设置为( 0 , 0),表明select会立即返回,允许应用程序对select操作进行“轮询”。出于对性能方面的考虑,应避免这样的设置。select成功完成后,会在fd_set结构中,返回刚好有未完成的I / O操作的所有套接字句柄的总量。若超过timeval设定的时间,便会返回0。不管由于什么原因,假如select调用失败,都会返回SOCKET_ERROR。用select对套接字进行监视之前,在自己的应用程序中,必须将套接字句柄分配给一个集合,设置好一个或全部读、写以及例外fd_set结构。将一个套接字分配给任何一个集合后,再来调用select,便可知道一个套接字上是否正在发生上述的I / O活动
另外一种设置为非阻塞模式的方法是通过网络消息和事件通知的方法,即listen(FSock,5);
//调用WSAAsyncSelect或WSAEventSelect函数的时候,会将套接字自动设为非锁定模式
if SOCKET_ERROR=WSAAsyncSelect(FSock,Handle,WM_SERVERSOCK,FD_READ or FD_ACCEPT) then
ShowMessage('WM_SOCKET Error');
然后在WM_SERVERSOCK这个自定义消息中,去判断是否有客户端发出连接的请求,再创建一个新的 socket与客户端进行通信,原socket则继续监听