• wrxsti (16.03.11 20:25) [0]
    Доброе время суток! Начал разбираться с портом завершения Windows и WinSock. Разобрался как создавать порт завершения, рабочие потоки, принимать подключения.. Но возник вопрос с использованием приема данных функцией WSARecv.
    Вот кусок кода:


    const
       BUF_SEND        = 1;
       BUF_RECV        = 2;

       BUF_RECV_LEN    = 3*1024;           // Длина буфера приема
       BUF_FILE_LEN    = 3*1024;            // Длина буфера отправки

     type
       TBuffer = record
                  pBuf: pointer;
                  iLenBuf: Cardinal;
                  iUsing: Integer;
                 end;
       pTBuffer = ^TBuffer;

       // Структура для описания ввода - вывода
       TIOData = record
                  lpOverlapped: TOverlapped;
                  pBuffer: pTBuffer;
                  iByteTrans: Cardinal;   // если передается файл то здесь храним дескриптор на файл

                  _WSABuf: WSABUF;
                  iType: Cardinal;
                 end;
       PTIOData = ^TIOData;

       // Структура клиента или данные описателя - сокета
       TClient = record
                  sName: string[20];
                  Sock: TSocket;
                  iCountBuf: Integer;
                  ioDataRecv: TIOData;
                  LastMes: Integer;
                 end;
       PTClient = ^TClient;
    .....

    class function TIOWSTCPSERVER.CompletionPortThread(Param: pointer): DWord;
    var BytesTransferred: Cardinal;
       pPer: pTIOData;
       pCl: pTClient;
       st : string;
    begin
    while true
    do begin
        if not GetQueuedCompletionStatus(TIOWSTCPSERVER(Param).FhCompletionPort, BytesTransferred, DWORD(pCl), POverlapped(pPer), INFINITE)
        then begin
              TIOWSTCPSERVER(Param).FreeClient_sec(pCl);
              Continue;
             end;

       // Клиент отключился WSARecv "вернулась"
       if BytesTransferred = 0
       then begin
             //FormatDiag('Клиент разорвал связь...');
             //InterlockedDecrement(pCl^.iCountBuf);
             TIOWSTCPSERVER(Param).FreeClient_sec(pCl);
             Continue;
            end;

        case pPer^.iType
        of
         BUF_RECV : begin
                     // Приняли данные от клиента
                     pCl^.ioDataRecv.iByteTrans := BytesTransferred;
                 
                     st := String(pCl^.ioDataRecv.pBuffer^.pBuf);
                     // Иниц. след цикл приема
                     TIOWSTCPSERVER(Param).InitClientSocket(pCl);
                    end;
        end;
       end;

    ExitThread(0);
    end;




    Вопрос в том что если я поставлю BUF_RECV_LEN  = 1*1024 или BUF_RECV_LEN  = 2*1024
    то при получении данных на строке st := String(pCl^.ioDataRecv.pBuffer^.pBuf); вылетает ошибка "access violation at 0x75dd9f11: read of address 0x01510000". Вот и не понимаю в чем проблема, отправляю данных то всего на 90 байт: строку " --- 1234567890zxcvbnmasdfghjklqwertyuiopячсмитьбюфывапролджэйцукенгшщзхъ!". А если сделать BUF_RECV_LEN  = 3*1024, то строка приходит полностью, но если отослать к примеру 2701 байта, то опять выскакивает та же ошибка.. Почему так? ведь буфер размером 3072 байта! а если убрать из кода строку st := String(pCl^.ioDataRecv.pBuffer^.pBuf); то он принимает ровно столько байт, сколько отправлено.. Для примера с посылкой 2701 байта данные придут двумя пакетами, первый придет 1460 байт и второй 1241.. Как правильно принять данные, и почему он его разделил на два пакета, ведь опять же буфер то 3072 байта? Помогите, пожалуйста, разобраться и что нибудь посоветуйте)) премного буду благодарен))
  • acdev (24.03.11 15:00) [1]
    Посмотрите на исходники HPScktSrvr (HPSocketServer).
    По вашему коду можно лишь судить о том, что мало статей прочитали.
  • Slym © (25.03.11 09:55) [2]
    нинадо String(pointer) - оно ищет нуль, и не находя вылазит за буфер, надо SetString - четко указывая размер
Есть новые Нет новых   [134437   +27][b:0][p:0.002]