Проблем с передачей файла в потоках

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by _nic, 25 Sep 2008.

  1. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Передающая сторона
    Code:
    void thr(void *Pvoid)
    {WSASetLastError(0);
    SOCKET s;SOCKADDR_IN adr;DWORD rb;unsigned long ss,sz;int p=1;
    WSADATA wsd;WSAStartup(MAKEWORD(1,1),&wsd);
    adr.sin_family=AF_INET;
    adr.sin_port=htons(3060);
    adr.sin_addr.s_addr=inet_addr("127.0.0.1");
    s=socket(AF_INET,SOCK_STREAM,0);
    connect(s,(sockaddr*)&adr,sizeof(adr));SetLastError(0);
    HANDLE f=CreateFile(fnam,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,0);
    char *buf=new char[(1024*1024)*10];
    DWORD e=GetFileSize(f,&ss);
    if(e>0){sz=e;}if(e<1){sz=ss;}
    if(sz<(1024*1024)*10)
    {ReadFile(f,buf,sz,&rb,0);send(s,buf,rb,0);}
    if(sz>(1024*1024)*10)
    {
    for(;;)
    {
    ReadFile(f,buf,(1024*1024)*10,&rb,0);
    sz=sz-(1024*1024)*10;send(s,buf,rb,0);
    memset(buf,NULL,(1024*1024)*10);MessageBox(0,CurrToStr((int)WSAGetLastError()).c_str(),"!!!",MB_OK);
    SetFilePointer(f,((1024*1024)*10)*p,NULL,FILE_BEGIN);p++;
    if(sz<(1024*1024)*10){ReadFile(f,buf,sz,&rb,0);send(s,buf,strlen(buf),0);break;}
    }
    }
    }
    
    Принимающая сторона
    Code:
    void loader(void *Pvoid)
    {
    SOCKET s,s1;WSADATA wsd;SOCKADDR_IN ladr,adr;DWORD bw;
    WSAStartup(MAKEWORD(1,1),&wsd);
    ladr.sin_family=AF_INET;
    ladr.sin_port=3060;
    ladr.sin_addr.s_addr=inet_addr(0);
    s=socket(AF_INET,SOCK_STREAM,0);
    bind(s,(sockaddr*)&ladr,sizeof(ladr));int sz=sizeof(adr);
    listen(s,1);s1=accept(s,(sockaddr*)&adr,&sz);
    char *buf=new char[(1024*1024)*10];InitializeCriticalSection(&cs1);
    EnterCriticalSection(&cs1);
    HANDLE f=CreateFile(outf,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_FLAG_RANDOM_ACCESS,0);
    LeaveCriticalSection(&cs1);int szc;
    for(;;)
    {
    szc=recv(s1,buf,(1024*1024)*10,0);MessageBox(0,CurrToStr(szc).c_str(),"!!!",MB_OK);
    if(szc<=0){break;}
    WriteFile(f,buf,szc,&bw,NULL);
    memset(buf,NULL,(1024*1024)*10);Sleep(100);
    }CloseHandle(f);
    }
    
    Немогу понять по чему неработает :( На передающей стороне WSAGetLastError вовращает 10057(тоесть WSAENOTCONN) .Но как такое может быть если при запуске передающего потока в принимающем срабатывает accept :confused:
     
  2. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    тут много неправильного.
    Про отдающую сторону:
    структуру SOCKADDR_IN надо обнулить перед использованием (точнее некоторые ее поля)

    Code:
    DWORD e=GetFileSize(f,&ss);
    if(e>0){sz=e;}if(e<1){sz=ss;}
    
    в переменную ss вообще-то записывается старшая часть 64-битного размера файла, и смысл приведенных операций не совсем ясен

    потом неправильно организован цикл чтения и выдачи файла. Например вот так неправильно
    Code:
    ReadFile(f,buf,(1024*1024)*10,&rb,0);
    sz=sz-(1024*1024)*10;send(s,buf,rb,0);
    
    во-первых вовсе не факт что ReadFile прочтет именно 10 кб данных и никак не меньше. Во-вторых совсем не обязательно что send отправит именно столько данных сколько ему передали а не меньше
    Зачем здесь вызывается функция SetFilePointer непонятно.

    еще там используется strlen для бинарных данных, что никак недопустимо

    с принимающей стороной все еще хуже ошибок очень много
     
  3. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Во 1х вопрос был именно о проблеме с сокетами а не о других участках клда.
    Во 2х если ненравится то предлагаем свой вариант а не критикуем "ваш код плох,а где то есть лутчше"
    В 3х с принимающей стороны WSAGetLastError вернуло WSAENOTSOCK
    Порылся глубже.Оказывается ноги растут от WSAEADDRNOTAVAIL на bind свмотрю внимательней вроде как не доглядел ladr.sin_port=3060; а надо ladr.sin_port=htons(3060); Думаю заработает.Не тут то было всеравно упорно выдает WSAEADDRNOTAVAIL :(
    Методом шаманского тыка обнаружил странную вещь если сделать так ladr.sin_addr.s_addr = inet_addr("127.0.0.1"); то работает.Но почему не катят не inet_addr(INADDR_ANY) не inet_addr(0) ??
     
    #3 _nic, 26 Sep 2008
    Last edited: 26 Sep 2008
  4. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    насчет принимающей стороны
    опять же не обнулил структуру ladr.
    что касается адреса хоста попробуй так:
    Code:
    ladr.sin_addr.s_addr=0;
    
    с критическими секциями я конечно могу ошибаться но мне кажется что там они ни к чему

    вообще, если ты собираешься просто передавать файл то рекомендуется отправлять его с помощью TransmitFile, это намного легче...
     
  5. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    О вот так все работает :) Спасибо.
    ЗЫ:мой код без TransmitFile и так нормально работает файлы передаются ,мд5сумм такого файла совпадает с мд5суммой исходного файла