我一直在为朋友和我做一个简单的winsock文件传输,无需每次都上传到mediafire而共享文件。但是我遇到的问题是/是(取决于你如何看待我当前的解决方案)我无法在不破坏文件的情况下发送文件。 目前我的发送/接收解决方案是:
procedure SenBuf(var buf;count:dword);
var
a, c: pointer;
cousend, tmp, left: dword;
begin
a := @buf;
cousend := 0;
left := count;
repeat
c := ptr(dword(a) + cousend);
tmp := Send(hSocket, c^, left, 0);
inc(cousend, tmp);
dec(left, tmp);
until cousend = count;
end;
procedure RecvBuf(var buf;count:dword);
var
a, c: pointer;
cousend, tmp, left: dword;
begin
a := @buf;
cousend := 0;
left := count;
repeat
c := ptr(dword(a) + cousend);
tmp := Recv(hSocket, c^, left, 0);
inc(cousend, tmp);
dec(left, tmp);
until cousend = count;
end;
但我正在使用tcp连接,为什么我需要检查发送/接收的字节并重新发送? (我知道原因是丢包,因为它在localhost上完美运行)。
它如何监听连接:
hServer := Socket(AF_INET,SOCK_STREAM,6);
sAddr.sin_family := AF_INET;
sAddr.sin_port := htons(wPort);
sAddr.sin_addr.S_addr := INADDR_ANY;
Bind(hServer, sAddr, SizeOf(sAddr));
winsock.Listen(hServer,3);
while not(Self.Terminated) do begin
iSize:=SizeOf(cAddr);
hClient:=Accept(hServer,@cAddr,@iSize);
if (hClient <> INVALID_SOCKET) then begin
sleep(50);
Client := TClient.Create(True);
Clients.Add(Client);
with Client do begin
hHost := inet_ntoa(cAddr.sin_addr);
Resume();
end;
/// incomplete code?
服务器 - 客户端:
procedure TClient.Execute;
var
mode: integer;
bytBuf: Array[0..255] of Char;
iRecv: Integer;
begin
inherited;
mode := 0;
ZeroMemory(@bytbuf, 256);
ioctlsocket(hSocket, FionBio, mode);
repeat
iRecv := Recv(hSocket, bytBuf, 256, 0);
if (iRecv <= 0) and (iRecv <> EWOULDBLOCK) then
break;
if not(bytbuf[0]=#0) then
Process(bytBuf);
ZeroMemory(@bytbuf,256);
until 1=2;
客户 - 客户:
procedure Start;
var
mode: integer;
begin
repeat
mode := 0;//blocking mode.
hSocket := Socket(AF_INET, SOCK_STREAM, 6);
ioctlsocket(hSocket, FionBio, mode);
Addr.sin_family := AF_INET;
Addr.sin_port := htons(hport);
Addr.sin_addr.S_addr := INET_ADDR(pchar(GetIPFromHost(cHost)));
if (winsock.Connect(hSocket,Addr, SizeOf(Addr)) = 0) then begin
SenStr('+');
WaitForServAndProcess;
end;
Sleep(20000);
lping:=GetTickCount;
until 1 = 2;
end;
有人会告诉我我的错误吗?或者给我发一个非常好的winsock教程?(不一定要用勺子)。
答案 0 :(得分:2)
您正在破坏文件数据,因为在调用WinSock的send()
和recv()
函数时您没有进行任何错误检查,例如:
procedure SenBuf(var buf; count:dword);
var
a: PByte;
tmp: Integer;
begin
a := PByte(@buf);
while count > 0 do begin
tmp := send(hSocket, a^, count, 0);
if tmp = SOCKET_ERROR then begin
if WSAEWOULDBLOCK = WSAGetLastError() then begin
// optionally use select() to detect when the socket is writable again...
Continue;
end;
// error!!! Stop sending...
Exit;
end;
inc(a, tmp);
dec(count, tmp);
end;
end;
procedure RecvBuf(var buf; count:dword);
var
a: PByte;
tmp: Integer;
begin
a := PByte(@buf);
while count > 0 do begin
tmp := recv(hSocket, a^, count, 0);
if tmp = SOCKET_ERROR then begin
if WSAEWOULDBLOCK = WSAGetLastError() then begin
// optionally use select() to detect when the socket is readable again...
Continue;
end;
// error!!! Stop reading...
Exit;
end;
if tmp = 0 then begin
// disconnected!!! Stop reading...
Exit;
end;
inc(a, tmp);
dec(count, tmp);
end;
end;
procedure TClient.Execute;
var
mode: integer;
bytBuf: Array[0..255] of Char;
iRecv: Integer;
begin
mode := 0;
ioctlsocket(hSocket, FionBio, mode);
repeat
iRecv := recv(hSocket, @bytBuf[0], SizeOf(bytBuf), 0);
if iRecv <= 0 then begin
// error or disconnected!!! Stop reading...
Exit;
end;
Process(bytBuf, iRecv);
until False;
end;