楼主,叫你看看SendStream的代码你怎么不看呢? 这可是捷径,让你明白把数据可靠的发出去。。看懂再用, 别盲目抄. //----ScktComp.pas------------ function TCustomWinSocket.SendStreamPiece: Boolean; var Buffer: array[0..4095] of Byte; StartPos: Integer; AmountInBuf: Integer; AmountSent: Integer; ErrorCode: Integer;begin Lock;//锁定,为多线程安全 try Result := False; if FSendStream <> nil then begin if (FSocket = INVALID_SOCKET) or (not FConnected) then exit; while True do begin StartPos := FSendStream.Position; AmountInBuf := FSendStream.Read(Buffer, SizeOf(Buffer)); if AmountInBuf > 0 then begin AmountSent := send(FSocket, Buffer, AmountInBuf, 0);//AmountSent是发送出去的字节数. if AmountSent = SOCKET_ERROR then begin ErrorCode := WSAGetLastError; if ErrorCode <> WSAEWOULDBLOCK then begin Error(Self, eeSend, ErrorCode); Disconnect(FSocket); DropStream; if FAsyncStyles <> [] then Abort; Break; end else //WSAEWOULDBLOCK异常则让下次循环再发 begin FSendStream.Position := StartPos; Break; end; end else if AmountInBuf > AmountSent then FSendStream.Position := StartPos + AmountSent else if FSendStream.Position = FSendStream.Size then begin DropStream; Break; end; end else begin DropStream; Break; end; end; Result := True; end; finally Unlock;//解除锁定.. end; end;
你使用SendBuf的时候返回值要作必要判断.//非阻塞方式处理注意: For non-blocking sockets, the data is sent to the WinSock DLL which has it's own internal buffers. If the WinSock can accept additional data, SendBuf returns immediately with the number of bytes queued. If the WinSock internal buffer space is not able to accept the buffer being sent, SendBuf returns -1 and no data is queued at all. In this case, wait a bit for the WinSock to have a chance to send out already-queued data; then try again.//阻塞方式处理: For blocking sockets, SendBuf returns the number of bytes actually written. 如果你用的是SENDTEXT,它实际是调用了SendBuf function TCustomWinSocket.SendText(const s: string): Integer; begin Result := SendBuf(Pointer(S)^, Length(S)); end;
我不熟悉idtcpclient,和idtcpserver啊,你有这方面的例子吗?
把缓存给填满了之后,Sever端发来的数据丢掉了?
可以说清楚点吗?我不明白!你例子吗?我的E_MAIL:[email protected]给我一份源码,好吗?先谢谢你了!一定给分!
你说:“在Client端建个缓冲,然后用一个单独的线程处理缓冲里的数据”具体怎么建缓冲呀?你例子吗?我的E_MAIL:[email protected]给我一份源码,好吗?先谢谢你了!一定给分!
1、建立接收区(InofmationList:TStrings 在Form或DataModule的Creat里要先创建好)
procedure TDMSocket.AMClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
InofmationList.Add(Socket.ReceiveText);
ProcessData;//处理线程
end;2、ProcessData;//处理线程
while InofmationList.Count>0
begin
取出第一条处理,处理完了,清除掉第一条
end;
大体思路就这样
这样应该可以,但是,我发送的记录是很个字段的,12个字段,都是字符串的(除了1个字段外)分解时很麻烦哟!你有没有简单的办法来分解它们呀!请你说说思路好吗?我的QQ : 21673300 你在网上吗?你的QQ可以给我吗?
你可以用这里短信。
在Sever端发送的时候,你可先在把字段值用豆号分开如:'name,old,12,er45k,232'把这个作为一个记录发到Client端。以豆号作为分隔符分解就可以了pos,copy,等函数分解
你说:“你可以采用应答的模式,处理数据”,可以说得更具体一些吗,我不太明白,具体怎样做!谢谢!
,然后你接着发剩下的。如果是非阻塞方式,是写到缓存,返回失败你就这次全部重发。
参考它的源码。
我是采用的 ctNonBlocking 模式 ,请问一下, 你说的“如果是非阻塞方式,是写到缓存,返回失败你就这次全部重发。”是重发这条记录吗? “...写到缓存...”的具体原理是什么,你可以给我讲一下吗?先谢谢!你是这面的例子吗?给我一份好吗?我的 E_MAIl : [email protected] ! 你有ctBlocking模式的例子,请给我一份好吗? 我的QQ是 21673300, 我常在线,你可以用QQ给我讲一下吗?万分感谢!
{
int nleft;
int nread;
char *ptr;
ptr = vptr;
nleft = n;
while(nleft>0)
{
if( (nread = ::recv(fd, (char *)ptr, nleft, 0)) <0 )
{
if(nread == SOCKET_ERROR)
return -1;
}
else if(nread ==0)
{
break; //EOF
}
nleft -= nread;
ptr += nread;
}
return (n-nleft);
}//Write "n" bytes to a descriptor
int writen(SOCKET fd, const char *vptr, int n)
{
int nleft;
int nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while(nleft>0)
{
if( (nwritten = ::send(fd, ptr, nleft, 0)) <= 0)
{
if(nwritten == SOCKET_ERROR)
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
这可是捷径,让你明白把数据可靠的发出去。。看懂再用,
别盲目抄.
//----ScktComp.pas------------
function TCustomWinSocket.SendStreamPiece: Boolean;
var
Buffer: array[0..4095] of Byte;
StartPos: Integer;
AmountInBuf: Integer;
AmountSent: Integer;
ErrorCode: Integer;begin
Lock;//锁定,为多线程安全
try
Result := False;
if FSendStream <> nil then
begin
if (FSocket = INVALID_SOCKET) or (not FConnected) then exit;
while True do
begin
StartPos := FSendStream.Position;
AmountInBuf := FSendStream.Read(Buffer, SizeOf(Buffer));
if AmountInBuf > 0 then
begin
AmountSent := send(FSocket, Buffer, AmountInBuf, 0);//AmountSent是发送出去的字节数.
if AmountSent = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end else //WSAEWOULDBLOCK异常则让下次循环再发
begin
FSendStream.Position := StartPos;
Break;
end;
end else if AmountInBuf > AmountSent then
FSendStream.Position := StartPos + AmountSent
else if FSendStream.Position = FSendStream.Size then
begin
DropStream;
Break;
end;
end else
begin
DropStream;
Break;
end;
end;
Result := True;
end;
finally
Unlock;//解除锁定..
end;
end;
For non-blocking sockets, the data is sent to the WinSock DLL which has it's own internal buffers. If the WinSock can accept additional data, SendBuf returns immediately with the number of bytes queued. If the WinSock internal buffer space is not able to accept the buffer being sent, SendBuf returns -1 and no data is queued at all. In this case, wait a bit for the WinSock to have a chance to send out already-queued data; then try again.//阻塞方式处理:
For blocking sockets, SendBuf returns the number of bytes actually written. 如果你用的是SENDTEXT,它实际是调用了SendBuf
function TCustomWinSocket.SendText(const s: string): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S));
end;