互联网上传送出错,最后找到原因:原来每次发4k,客户端接收的时候好像一次收不完,本来我的数据都是有
包头的,可是如果客户端一次没收完,剩下来的数据客户端接收到之后由于没有包头,他不认识就给丢弃了。怎么会出现我发一个数据包,在客户端分多次到达的情况????
我把发送缓冲区调整为1K之后,传送过程就非常不错,没有出现一次错误!!
大家碰到过这种情况吗?? 如果调为1K,传送速度非常的慢,可是我又不知道将速度定为多少合适,
大家都是怎么解决这样的问题的呢??
包头的,可是如果客户端一次没收完,剩下来的数据客户端接收到之后由于没有包头,他不认识就给丢弃了。怎么会出现我发一个数据包,在客户端分多次到达的情况????
我把发送缓冲区调整为1K之后,传送过程就非常不错,没有出现一次错误!!
大家碰到过这种情况吗?? 如果调为1K,传送速度非常的慢,可是我又不知道将速度定为多少合适,
大家都是怎么解决这样的问题的呢??
其实在VCL里面有几处可以参考..
如果是DELPHI6及以下,可以看下面的实现.
或者看看INDY控件组件实现.//scktcomp.PAS单元.function TCustomWinSocket.SendStreamPiece: Boolean;
var
Buffer: array[0..4095] of Byte;
StartPos: Integer;
AmountInBuf: Integer;
AmountSent: Integer;
ErrorCode: Integer; procedure DropStream;
begin
if FDropAfterSend then Disconnect(FSocket);
FDropAfterSend := False;
FSendStream.Free;
FSendStream := nil;
end;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);//注意,这儿的返回值很重要.
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
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;
...
date/time 什么的等等
...
Size: Int64;
end;ok.. send 部分...
SendBuf(FileHdr, sizeof(TFileHdr));
RemainBytes := FileHdr.Size;
while RemainBytes <> 0 do
begin
RemainBytes := RemainBytes - SendBuf(内容)
end;
我想一问一答的模式也是可以行的通的。
而你所说的第2种情况是不会出现的。
while size > 0 do
begin
SendCount:=Socket.SendBuf(buf,size);
if SendCount < 0 then Continue;
size:= size -SendCount;
end;SendCount 是实际发送的大小,它不一定等于size ,尤其是在互联网上网络不好的情况下。所以最好循环发送,知道发完为止。
jadeluo(秀峰)说得很对
while size > 0 do
begin
SendCount:=Socket.SendBuf(buf,size);
if SendCount < 0 then Continue;
size:= size -SendCount;
end;我现在采用客户端收到数据进行重组的问题,但发现收到的数据不是发送方的数据.是不是我的发送方的代码有问题?
我是直接一次发送缓冲区内所有的内容,可能很大,也可能很小,我现在用的文件就413字节,但发到客户端接收到的不是原内容,郁闷呀!!
fLength:=GetFileLen(ExtractFilePath(application.ExeName) + 'data\' + downList.Strings[i]);
FileHandle:=FileOpen(ExtractFilePath(application.ExeName) + 'data\' + downList.Strings[i],fmOpenReadWrite); //因为一个文件多次激发该事件,所以不能在此删除文件,删除文件的控制在发送DownRequ命令之前
FileSeek(fileHandle,0,0);
setLength(fileBuf,fLength);
FileRead(fileHandle,fileBuf[0],fLength);
FileClose(fileHandle);
//
strFormatFName:=downList.Strings[i] + ' ';
strFormatFName:=leftstr(strFormatFName,30);
setLength(sendBuf,40 + fLength);
CopyMemory(sendBuf,PChar('@^NEWFILE:' + strFormatFName),40);
pSendBuf:=sendBuf;
pSendBuf:=pointer(Integer(pSendBuf) + 40);
CopyMemory(pSendBuf,fileBuf,fLength-1);
Socket.SendBuf(sendBuf,fLength);
if(i=downList.Count-1) then Socket.SendText('@^NEWFILE:');
status.Panels[2].Text:='正在发送新文件:' + downList.Strings[i];
fileBuf:=nil;
sendBuf:=nil;
现在我不想把数据分包,有人能告诉我发送方为什么不分包发送,客户端接收重组的时候数据是错的原因吗?
我怎么知道
sendBuf,sendBuf[0]还有区别吗?另外接收的时候,为什么还要带^,这是什么意思?
pBuffer:Pointer;
Socket.ReceiveBuf(pBuffer^,recvLen);
看看帮助吧另外Socket使用阻塞模式时数据是一次发送或者接收完成的,至少我们可以这么认为。
1)粘包问题
2)延时重发问题
粘包我想就不用说了,例如需要传多个文件,需要自己定协议,重组接收缓冲区,判断文件分隔的地方.
现在又发现了TCP的延时重发问题,就是说tcp仅仅保证数据发送的正确性,而不保证顺序.如果服务端发现前面的数据发错了,会重发那些错误数据,而客户端接收的时候,根本就没法判断哪些是错误数据,哪些是正确数据.而且重发的那些数据并不一定紧跟在出错的数据之后就发过来,而是有可能出错之后接着发送有效数据,过一阵子,服务器端突然又把前面出错的数据给重发过来了,晕啊!!!!传送文件就这么难写吗????
2。BUF设置512最好,