delphi ClientSocket的属性ClientType设置成ctNonBlocking无法捕获异常,该怎么处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi ClientSocket的属性ClientType设置成ctNonBlocking无法捕获异常,该怎么处理相关的知识,希望对你有一定的参考价值。

最近在用delphi的ClientSocket写一个应用程序,需要不断的循环登录到不同的远程服务器上取数据,然后将结果保存为文本文件存放在本地,由于需要不断的循环读取信息,因此我把这部分循环放到了线程里面执行。可是在使用ClientSocket的时候,发现将ClientSocket的属性ClientType设置成ctNonBlocking状态时,程序就无法通过try..except..end捕获异常,这就导致一旦有一台服务器无响应时,程序就无法跳出本次循环,继续下一个循环。可如果将ClientSocket设置成ctBlocking,倒是可以捕获异常了,可是ClientSocket的OnRead事件又无法响应了。按照帮助里面的信息,如果将ClientSocket设置成了ctBlocking,就需要使用TWinSocketStream来读写信息,请问我该怎么实现这部分功能?各位大虾有没有相应的例子可以参考一下,谢谢。。

参考技术A ClientSocket1.Socket.SendBuf(buf, int)
ClientSocket1.Socket.ReceiveBuf(buf, int)
这两个方法基本都能实现各种功能追问

有具体的示例么?能否给个例子参考一下,谢谢。

delphi serversocket与clientsocket通讯的问题?

2个或以上clientsocket连接serversocket,serversocket如何区分不同的客户端?用ListBox显示连接的客户端,如何给不同的客户端发信息?
注意:是 delphi
1楼的,你的代码没有我要的功能。。。我的要求是,选择ListBox中显示连接的N个客户端中任意一个,通过button,按钮,发送信息。。。这个如何实现?
我现在是:for i:=0 to sessions do
begin //取得匹配的客户端
if session[i].CName = trim(edtServer.Text) then
begin
//.......
end
end;
我的程序有个问题,就是,登陆N个客户端,客户端给服务器发信息没问题,但是服务端只能给N-1个客户端发信息

serversocket源码:
const
CMax=10; //客户端最大连接数,具体需求,自己设置
type
client_record=record
CHandle: integer; //客户端套接字句柄
CSocket:TCustomWinSocket; //客户端套接字
CName:string; //客户端计算机名称
CAddress:string; //客户端计算机IP地址
CUsed: boolean; //客户端联机标志
end;
//////////////
session: array[0..CMax] of client_record; //客户端连接数组
Sessions: integer;

//打开套接字连接,并使套接字进入监听状态
procedure TfrmServerMain.tbConnectClick(Sender: TObject);
begin
serversocket.Port:=9999;//监听端口
ServerSocket.Open ;
end;
//关闭套接字连接,不再监听客户端的请求
procedure TfrmServerMain.tbDisconnectedClick(Sender: TObject);
begin
ServerSocket.Close;
StatusBar.Panels[0].Text :='服务器套接字连接已经关闭,无法接受客户端的连接请求.';
end;
//从客户端读取信息
procedure TfrmServerMain.ServerSocketClientRead(Sender: TObject;Socket: TCustomWinSocket);

var
i:integer;
begin
//将从客户端读取的信息添加到Memo1中
Memo1.Lines.Add(Socket.ReceiveText);
for i:=0 to sessions do
begin
//取得匹配的客户端
if session[i].CHandle = Socket.SocketHandle then
begin
session[i].CSocket.SendText('回复客户端'+session[i].CAddress+' ==> '+Edit1.Text);
end;
end;
end;
//服务器端套接字进入监听状态,以便监听客户端的连接
procedure TfrmServerMain.ServerSocketListen(Sender: TObject;Socket: TCustomWinSocket);
begin
StatusBar.Panels[0].Text :='等待客户端连接...';
end;
//当客户端连接到服务器端以后
procedure TfrmServerMain.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i,j:integer;begin
begin
j:=-1;
for i:=0 to sessions do
begin
//在原有的客户端连接数组中有中断的客户端连接
if not session[i].CUsed then
begin
session[i].CHandle := Socket.SocketHandle ;//客户端套接字句柄
session[i].CSocket := Socket; //客户端套接字
session[i].CName := Socket.RemoteHost ; //客户端计算机名称
session[i].CAddress := Socket.RemoteAddress ;//客户端计算机IP
session[i].CUsed := True; //连接数组当前位置已经占用
Break;
end;
j:=i;
end;
if j=sessions then
begin
inc(sessions);
session[j].CHandle := Socket.SocketHandle ;
session[j].CSocket := Socket;
session[j].CName := Socket.RemoteHost ;
session[j].CAddress := Socket.RemoteAddress ;
session[j].CUsed := True;
end;
StatusBar.Panels[0].Text := '客户端 '+Socket.RemoteHost + ' 已经连接';
end;
//当客户端断开连接时
procedure TfrmServerMain.ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
for i:=0 to sessions do
begin
if session[i].CHandle =Socket.SocketHandle then
begin
session[i].CHandle :=0;
session[i].CUsed := False;
Break;
end;
end;
StatusBar.Panels[0].Text :='客户端 '+Socket.RemoteHost + ' 已经断开';
end;
//关闭窗口
procedure TfrmServerMain.tbCloseClick(Sender: TObject);
begin
Close;
end;
procedure TfrmServerMain.FormCreate(Sender: TObject);
begin
sessions := 0;
end;
procedure TfrmServerMain.FormClose(Sender: TObject;var Action: TCloseAction);
begin
ServerSocket.Close ;
end;
//当客户端正在与服务器端连接时
procedure TfrmServerMain.ServerSocketGetSocket(Sender: TObject;
Socket: Integer; var ClientSocket: TServerClientWinSocket);
begin
StatusBar.Panels[0].Text :='客户端正在连接...';
end;
//客户端发生错误
procedure TfrmServerMain.ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
StatusBar.Panels[0].Text :='客户端'+Socket.RemoteHost +'发生错误!';
ErrorCode := 0;
end;
====================================================================
客户端源码:
procedure TfrmClientMain.tbConnectedClick(Sender: TObject);
begin
ClientSocket.Host:=‘127.0.0.1’;//连接IP
ClientSocket.Port:=9999; //连接端口
ClientSocket.Open ;
end;
//关闭套接字连接
procedure TfrmClientMain.tbDisconnectedClick(Sender: TObject);
begin
ClientSocket.Close;
end;
//接受服务器端的回复
procedure TfrmClientMain.ClientSocketRead(Sender: TObject;Socket: TCustomWinSocket);
begin
Memo1.Lines.Add(Socket.ReceiveText);
end;
//发送信息到服务器端
procedure TfrmClientMain.tbSendClick(Sender: TObject);
begin
ClientSocket.Socket.SendText(Edit1.Text);
end;
procedure TfrmClientMain.tbCloseClick(Sender: TObject);
begin
Close;
end;
//设置要连接的服务器端地址
procedure TfrmClientMain.FormShow(Sender: TObject);
begin
ClientSocket.Host := SocketHost;
end;
//已经连接到服务器端
procedure TfrmClientMain.ClientSocketConnect(Sender: TObject;Socket: TCustomWinSocket);
begin
tbSend.Enabled := True;
tbDisconnected.Enabled :=True;
btnSend.Enabled := True;
StatusBar.Panels[0].Text := '已经连接到 '+ Socket.RemoteHost ;
end;
//正在连接到服务器端
procedure TfrmClientMain.ClientSocket1Connecting(Sender: TObject;Socket: TCustomWinSocket);
begin
StatusBar.Panels[0].Text := '正在连接到服务器... ' ;
end;
//当断开与服务器端的连接时发生
procedure TfrmClientMain.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
tbSend.Enabled := False;
btnSend.Enabled := False
tbDisconnected.Enabled := False;
StatusBar.Panels[0].Text := '已经断开与 '+ Socket.RemoteHost +' 的连接';
end;
procedure TfrmClientMain.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
ClientSocket.Close ;
end;
//当与服务器端的连接发生错误时
procedure TfrmClientMain.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;var ErrorCode: Integer);
begin
StatusBar.Panels[0].Text := '与服务器端的连接发生错误';
ErrorCode := 0;
end;
end.
参考技术A clientsocket和serversocket都不能用于实例
它们通常只作为socket函数的参数出现
在delphi中,使用socket必须指协议类型
如tcpserver,tcpclient,udpserver,udpclient等等
参考技术B 1.简单服务器
//#include <winsock2.h>
//#pragma comment(lib,"WS2_32.lib")
WSADATA wsd;
static UINT port=%%1;
UINT Listen(LPVOID pParam)

SOCKET sServer,sClient;
char buf[1024];
int retVal;
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

return -1;//失败

sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==sServer)

WSACleanup();
return -1;//创建套接字失败

SOCKADDR_IN addrServ;
addrServ.sin_family=AF_INET;
addrServ.sin_port=htons((short)pParam);
addrServ.sin_addr.s_addr=INADDR_ANY;
retVal=bind(sServer,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));
if(SOCKET_ERROR==retVal)

closesocket(sServer);
WSACleanup();
return -1;//绑定套接字失败

retVal=listen(sServer,1);
if(SOCKET_ERROR==retVal)

closesocket(sServer);
WSACleanup();
return -1;//开始监听失败

sockaddr_in addrClient;
int addrClientlen=sizeof(addrClient);
sClient=accept(sServer,(sockaddr FAR*)&addrClient,&addrClientlen);
if(INVALID_SOCKET==sClient)

closesocket(sServer);
WSACleanup();
return -1;//开始接受客户端连接失败

ZeroMemory(buf,sizeof(buf));
retVal=recv(sClient,buf,sizeof(buf),0);
if(SOCKET_ERROR==retVal)

closesocket(sServer);
closesocket(sClient);
WSACleanup();
return -1;//接收数据失败

CString %%2(buf);
closesocket(sServer);
closesocket(sClient);
WSACleanup();
return 0;

CWinThread *pThread=AfxBeginThread(Listen,&port);

2.简单客户端
//#include <winsock2.h>
//#pragma comment(lib,"WS2_32.lib")
WSADATA wsd;
SOCKET sHost;
SOCKADDR_IN servAddr;
char buf[1024];
int retVal;
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

return -1;//失败

sHost=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==sHost)

WSACleanup();
return -1;//创建套接字失败

servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr=inet_addr(%%3);
servAddr.sin_port=htons((short)%%2);
int nServAddlen=sizeof(servAddr);
retVal=connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr));
if(SOCKET_ERROR==retVal)
closesocket(sHost);
WSACleanup();
return -1;//连接服务器失败

ZeroMemory(buf,sizeof(buf));
strcpy(buf,%%3);
retVal=send(sHost,buf,sizeof(buf),0);
if(SOCKET_ERROR==retVal)

closesocket(sHost);
WSACleanup();
return -1;//向服务器发送数据失败

closesocket(sHost);
WSACleanup();

3.获得本机IP
//#include <winsock2.h>
//#pragma comment(lib,"WS2_32.lib")
WSADATA wsd;
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

return -1;//失败

char szHostname[100],szHostaddress[200];
if(gethostname(szHostname,sizeof(szHostname))!=SOCKET_ERROR)

HOSTENT *pHostEnt=gethostbyname(szHostname);
if(pHostEnt!=NULL)
sprintf(szHostaddress,"%d.%d.%d.%d",
( pHostEnt->h_addr_list[0][0]&0x00ff ),
( pHostEnt->h_addr_list[0][1]&0x00ff ),
( pHostEnt->h_addr_list[0][2]&0x00ff ),
( pHostEnt->h_addr_list[0][3]&0x00ff ));


else
return;
CString %%1(szHostaddress);

4.端对端通信
//#include <winsock2.h>
//#pragma comment(lib,"WS2_32.lib")
WSADATA wsd;
SOCKET s;
char buf[1024];
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

return -1;//失败

s=socket(AF_INET,SOCK_DGRAM,0);
if(s==INVALID_SOCKET)

WSACleanup();
return -1;//创建套接字失败

SOCKADDR_IN servAddr;
servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr=inet_addr(%%1);
servAddr.sin_port=htons(INADDR_ANY);
if(bind(s,(SOCKADDR*)&servAddr,sizeof(SOCKADDR_IN))==SOCKET_ERROR)

closesocket(s);
WSACleanup();
return -1;//绑定套接字失败

int nServAddrlen=sizeof(servAddr);
ZeroMemory(buf,sizeof(buf));
if(recvfrom(s,buf,sizeof(buf),0,(SOCKADDR*)&servAddr,&nServAddrlen)==SOCKET_ERROR)

closesocket(s);
WSACleanup();
return -1;//接收数据失败

CString %%2(buf);
ZeroMemory(buf,sizeof(buf));
strcpy(buf,%%3);
SOCKADDR_IN clientAddr;
clientAddr.sin_family=AF_INET;
clientAddr.sin_addr.s_addr=inet_addr(%%4);
clientAddr.sin_port=htons((short)%%5);
int nClientlen=sizeof(clientAddr);
if(sendto(s,buf,sizeof(buf),0,(SOCKADDR*)&clientAddr,nClientlen)==SOCKET_ERROR)

closesocket(s);
WSACleanup();
return -1;//向服务器发送数据失败

closesocket(s);
WSACleanup();

5.点对点通信
//#include <winsock2.h>
//#pragma comment(lib,"WS2_32.lib")
WSADATA wsd;
SOCKADDR_IN addrServ,addrServ2;
SOCKET sServer,sClient,sHost;
int retVal;
sockaddr_in addrClient;
char buf[1024];
static UINT port=%%2;
BOOL listenerRun=TRUE;
UINT Listen(LPVOID pParam)

addrServ.sin_family=AF_INET;
addrServ.sin_port=htons((UINT)pParam);
addrServ.sin_addr.s_addr=INADDR_ANY;
retVal=bind(sServer,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));
if(SOCKET_ERROR==retVal)

closesocket(sServer);
WSACleanup();
return -1;//绑定套接字失败

retVal=listen(sServer,1);
if(SOCKET_ERROR==retVal)

closesocket(sServer);
WSACleanup();
return -1;//开始监听失败

int addrClientlen=sizeof(addrClient);
sClient=accept(sServer,(sockaddr FAR*)&addrClient,&addClientlen);
if(INVALID_SOCKET==sClient)

closesocket(sServer);
WSACleanup();
return -1;//接收客户端请求失败

while(listenerRun)

ZeroMemory(buf,sizeof(buf));
retVal=recv(sClient,buf,sizeof(buf));
if(SOCKET_ERROR==retVal)

closesocket(sServer);
closesocket(sClient);
WSACleanup();
return -1;//接收客户端数据失败

CString %%4(buf);


if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

return -1;//失败

sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==sServer)

WSACleanup();
return -1;//创建套接字失败

CWinThread *pThread=AfxBeginThread(Listen,&port);
sHost=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==sHost)

WSACleanup();
return -1;//创建套接字失败

servAddr2.sin_family=AF_INET;
servAddr2.sin_addr.s_addr=inet_addr(%%1);
servAddr.sin_port=htons((short)%%3);
int nServerAddrlen=sizeof(servAddr2);
retVal=connect(sHost,(LPSOCKADDR)&servAddr2,sizeof(servAddr2));
if(SOCKET_ERROR==retVal)

closesocket(sHost);
WSACleanup();
return -1;//连接失败

zeroMemory(buf,sizeof(buf));
strcpy(buf,%%5);
retVal=send(sHost,buf,sizeof(buf),0);
if(SOCKET_ERROR==retVal)

closesocket(sHost);
WSACleanup();
return -1;//向发送数据失败

listenerRun=FALSE;
DWORD dwExitCode;
::GetExitCodeThread(pThread->m_hThread,&dwExitCode);
pThread=null;
closesocket(sServer);
closesocket(sClient);
closesocket(sHost);
WSACleanup();
参考技术C for i:=low(sessions) to High(sessions) do
begin

end;

以上是关于delphi ClientSocket的属性ClientType设置成ctNonBlocking无法捕获异常,该怎么处理的主要内容,如果未能解决你的问题,请参考以下文章

delphi serversocket与clientsocket通讯的问题?

Delphi TServerSocket/ClientSocket 发送接收消息问题请教

delphi使用clientsocket指定端口号

怎么在Delphi 的ClientSocket 中设置超时时间??急!

在delphi中如何用clientsocket进行实时发送。。即在数据库读取到数据就立即发送出去。。

怎样用delphi获取远端服务器端口TCP/IP协议数据