看了些资料
An FD_WRITE message is posted when a socket is first connected with connect or WSAConnect (after FD_CONNECT, if also registered) or accepted with accept or WSAAccept, and then after a send operation fails with WSAEWOULDBLOCK and buffer space becomes available.function TMyTcpClient.SendBuf(var buf; const iLen: Integer): integer;
var
ss: string;
iErr: Integer;
begin
Result := Socket_error;
if (FSocket <> Invalid_socket) and FActive then
begin
Result := winsock2.send(FSocket, buf, iLen, 0);
if (Result = Socket_error) or (Result <> iLen) then
begin
iErr := WSAGetLastError();
ss := 'Send data error: ' + IntToStr(iErr);
DoError(self, seSend, PChar(ss), iErr);
if iErr <> WSAEWOULDBLOCK then
begin
DoClose;
end end;
end;
end;
请问我要怎么改?网上看了 说要
等待 FD_WRITE 继续发送 不知道怎么做?求指点
An FD_WRITE message is posted when a socket is first connected with connect or WSAConnect (after FD_CONNECT, if also registered) or accepted with accept or WSAAccept, and then after a send operation fails with WSAEWOULDBLOCK and buffer space becomes available.function TMyTcpClient.SendBuf(var buf; const iLen: Integer): integer;
var
ss: string;
iErr: Integer;
begin
Result := Socket_error;
if (FSocket <> Invalid_socket) and FActive then
begin
Result := winsock2.send(FSocket, buf, iLen, 0);
if (Result = Socket_error) or (Result <> iLen) then
begin
iErr := WSAGetLastError();
ss := 'Send data error: ' + IntToStr(iErr);
DoError(self, seSend, PChar(ss), iErr);
if iErr <> WSAEWOULDBLOCK then
begin
DoClose;
end end;
end;
end;
请问我要怎么改?网上看了 说要
等待 FD_WRITE 继续发送 不知道怎么做?求指点
解决方案 »
- INDY 9.0 ★★★ idTcpClient.ReadStream 时停在那了?
- 怎么样使richedit 里面很多行文字 点任何一行 该行就是选中状态 怎样做最好
- 请前辈指教:点击APPAND按钮新增一条记录,用Field.AsDateTime+1的方式实现了新增记录中日期的自动填写,可为什么有时会乱写,如2005-06-07
- ApdComPort控件的接收问题.
- fastreport2.5导出word出现乱码怎么解决!急。
- [Fatal Error] uMapInfo.pas(6): File not found: 'Ole2.dcu'
- 请好心的朋友帮忙写个com组件程序
- 谁能告诉我括号中的意思(关于midi内码)
- 系统托盘的图标?
- BDE的BatchMove好用吧!但它只适用于BDE,有谁知道有什么构件可以适用任何数据访问呢?
- 在控件image上显示的图片不清晰
- IdTCPServer IdTCPClient 双向接发消息已经实现 但碰到了一个很奇怪的问题
procedure DoProc(Sender: TObject);
var
iLocalIdx, iStartIdx, iWaitNum, idx: integer;
NetwEvt: TWSANetworkEvents;
j: Cardinal;
i: Integer;
Evt: WSAEVENT;
Skt: TSocket;
tcpClt: TMyTcpClient;
ss: string;
iErr: Integer;
begin
try
if TMythread(Sender).WaitNum <= 0 then
begin
if not TMythread(Sender).IsPause then
TMythread(Sender).Suspend;
Exit;
end; Evt := 0;
Skt := -1; //对事件对象数组进行检查网络事件(即等待某个事件的触发)
idx := WSAWaitForMultipleEvents(TMythread(Sender).WaitNum, TMythread(Sender).GetFirstEvtAddr, False, I_MaxWaitTime, False); if (idx >= I_WaitMaxEvt) or (idx < 0)then
begin
if idx = Socket_error then
begin
Sleep(I_MaxFreeWaitTime);
//应该要调整,去掉Evt=0,或者Socket=-1的
end;
Exit;
end;
idx := idx - wsa_wait_event_0; if TMythread(Sender).SktEvtItems[idx] = nil then Exit;
skt := TMythread(Sender).SktEvtItems[idx].SockID;
Evt := TMythread(Sender).SktEvtItems[idx].EventId; FillChar(NetwEvt.lNetworkEvents, sizeof(NetwEvt), 0); WSAEnumNetworkEvents(Skt, Evt, @NetwEvt); j := NetwEvt.lNetworkEvents;
if ((j and FD_Read) > 0) or ((j and FD_OOB) > 0) then
begin
if (j and FD_Read) > 0 then
begin
iErr := NetwEvt.iErrorCode[FD_Read_BIT];
if iErr = 0 then
ProcSockEvt(sender, FD_Read, skt)
else
begin
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(skt));
if tcpClt <> nil then
begin
ss := 'Receive data error, ' + IntToStr(iErr);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seReceive, PChar(ss), iErr);
if (iErr >= 10050) and (iErr <= 10058) then
begin //严重错误要关闭Socket
if iErr <> 10056 then
ProcSockEvt(sender, FD_Close, skt);
end;
end;
end;//end of
end;
if (j and FD_OOB) > 0 then //暂时没用到
begin
iErr := NetwEvt.iErrorCode[FD_OOB_BIT];
if NetwEvt.iErrorCode[FD_OOB_BIT] = 0 then
begin
ProcSockEvt(sender, FD_OOB, skt); //OK去掉注释可用
//Exit;// 带外的不做处理
end
else
begin
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(skt));
if tcpClt <> nil then
begin
ss := 'Receive OOB data error, ' + IntToStr(iErr);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seReceive, PChar(ss), iErr);
end;
end;//end of
end;
end
else
if (j and FD_Close) > 0 then
begin
iErr := NetwEvt.iErrorCode[FD_Close_BIT];
if iErr <> 0 then
begin
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(skt));
if tcpClt <> nil then
begin
ss := 'Close Socket error, ' + IntToStr(iErr);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seClose, PChar(ss), iErr);
end;
end;//end of
ProcSockEvt(sender, FD_Close, skt);
end
else
if (j and FD_Write) > 0 then
begin
iErr := NetwEvt.iErrorCode[FD_Write_BIT];
if iErr = 0 then
ProcSockEvt(sender, FD_Write, skt)//这里没做处理,是个空的,不知道要怎么处理?
else
begin
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(skt));
if tcpClt <> nil then
begin
ss := 'Write data error, ' + IntToStr(iErr);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seSend, PChar(ss), iErr);
end;
end;//end of
end;
//一下是ProcSockEvt的FD_wrie消息,
procedure ProcSockEvt(Sender: TObject; const iOpt, iSocket: Integer);
var
AccAddr: TSockAddrIn;
err, i, j, iLen, lenAddr: Integer;
PNetwEvt: PWSANetworkEvents;
evt: wsaevent;
SktEvt: TMySktEvtItem;
tcpClt: TMyTcpClient;
ss: String;
P: Pointer;begin
case iOpt of
Fd_read:
begin
iLen := TMyTcpBase.GetRecLength(iSocket);
if iLen <= 0 then
Exit;
P := GlobalAllocPtr(GPTR, iLen * SizeOf(Byte));
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(iSocket));
if p = nil then
begin
if tcpClt <> nil then
begin
err := GetLastError;
ss := 'Receive data error, alloc global memory failed: ' + IntToStr(err);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seReceive, PChar(ss), err);
tcpClt.Close;
end;
Exit;
end;
try
try
J := recv(iSocket, TMyArrByte(P)[0], iLen, 0);
if tcpClt = nil then Exit;
if (J <= 0) or (J <> iLen) then
begin
if tcpClt <> nil then
begin
if Assigned(tcpClt.OnErrorMsg) then
begin
err := WSAGetLastError;
//ss := '接收数据出错: ' + IntToStr(err);
ss := 'Receive data error: ' + IntToStr(err);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seReceive, PChar(ss), err);
end;
end;
Exit;
end
else
begin // J > 0 and J = iLen
if Assigned(tcpClt.OnReceiveMsg) then
begin
tcpClt.OnReceiveMsg(tcpClt, Cardinal(P), J); //OK 事件处理 ,这是线程事件
end;
end; //end of // J > 0 and J = iLen
finally
if P <> nil then
GlobalFreePtr(P);
end;
except
on E: Exception do
begin
if tcpClt <> nil then
begin
err := WSAGetLastError;
ss := 'Receive data exception.' + IntToStr(err);
if Assigned(tcpClt.OnErrorMsg) then
tcpClt.OnErrorMsg(tcpClt, seReceive, PChar(ss), err);
end;
end;
end; // end of try except
end; //FD_Read
fd_close:
begin
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(iSocket));
if tcpClt <> nil then
begin
PostMessage(tcpClt.Handle, WM_MYSOCKETMSG, iSocket, FD_CLOSE);
// end of
end;
end;
Fd_oob:
begin
iLen := 1; //MSG_oob只有一个
P := GlobalAllocPtr(GPTR, iLen * SizeOf(Byte));
try
J := recv(iSocket, TMyArrByte(P)[0], iLen, MSG_OOB);
tcpClt := TMyTcpClient(TMythread(Sender).GetTcpclientBySkt(iSocket));
if tcpClt = nil then Exit;
if (J > 0) then
begin
if Assigned(tcpClt.OnReceiveMsg) then
tcpClt.OnReceiveMsg(tcpClt, Cardinal(P), J);
end;
finally
GlobalFreePtr(P);
end;
end;//end of FD_OOB
FD_WRITE://不知道要怎么处理?
begin end;
end;//end of case
end;
是在收到wsaewouldblock,立即把当前的socket转成缓冲区模式
所有要发出的数据填充到一个缓冲区队列
在收到FD_WRITE之后再从缓冲区开始发送
一直到数据发完才把socket转为实时发送