2013-04-16 2 views
1

저는 매번 mediafire에 업로드 할 필요없이 친구와 저에게 간단한 winsock 파일 전송 작업을 해왔습니다. 그러나 내가 겪었던 문제는/현재의 해결책을 보는 방법에 달려 있습니다. 파일을 손상시키지 않고 보낼 수 없습니다. 현재/수신을 보내는 내 솔루션은 다음과 같습니다tcp를 사용하여 송수신을 보장합니까?

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 연결을 사용하고 있는데, 왜 내가/전송 받아이를 다시 전송되는 바이트를 확인해야? (이유는 로컬 호스트에서 완벽하게 작동하기 때문에 패킷이 떨어지는 이유입니다).

가 연결을 수신하는 방법 :

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 튜토리얼? (spoonfed 할 필요는 없습니다).

+1

난 당신이 이미 인디 등 도서관에서 다른 사람에 의해 해결 문제를 해결하기 위해 너무 열심히하려는 생각, 내 제안은이 시간을 낭비 중지하고 그것을 사용하는 것입니다. – ComputerSaysNo

+1

다른 사람의 작업을 사용하는 대신 왜 발생하는지 이유를 이해하고 싶습니다./ – user0

+0

@ user0 글쎄, 내가 알고있는 바로는 TCP는 패킷이 대상 **에 도착하고 ** 보낸 된 순서대로 그렇게 오래도록 보장합니다. 네트워크 전문가가 아니라 값 비싸지 않은 것에 대해 유감스럽게도 연결에 너무 이상한 상황이 발생하지 않기 때문에 : – ComputerSaysNo

답변

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; 
+0

정말 고마워요, 나는 오류를 검사 한 적이 없지만 그 일을해야한다고 생각합니다. 보내. – user0

관련 문제