Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.10.2015, 16:50   #1
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию сокеты и jpeg

Здравствуйте, хочу сделать что то типа радмина но для локальной сети (в кабинет информатики)
Клиент посылает серверу запрос (1 байт), сервер начинает отправлять снимок с экрана в формате jpg. Передаёт файл не ломая его, но почему то клиент странно его принимает, либо не тот кусок, либо странный размер.
Отправляются по 10240 байта, но логи показывают что первый пакет принят но размер у него меньше (5000 байт допустим) или любой другой, и остальные пакеты принимаются и даже количество у них совпадает с отправленными. Бывает что примется пакета 3-4 либо последний пакет не принимается, он просто не приходит либо приходит в середине передачи (последний пакет помечается первым байтом со значением 4). Записываю все переданные байты сервера в файл и картинка нормальная, клиент же записывает картинку в файл и она искажена, разноцветная, короче что то ужасное с ней. Подскажите пожалуйста.
Много всего закомменчено, прошу не ругаться

Сервер: (находится на компьютерах учеников)
Код:
const
  PEPPA_PORT = 25846;
  PEPPA_BUFLEN = 1024*10-1;

  PEPPA_PING = 1;
  PEPPA_PONG = 2;

  PEPPA_SCREENN = 3;  // запрос на новый скрин / он же пометка что начата передача нового файла
  PEPPA_SCREENA = 4;  // пометка в пакете что это часть скрина
  PEPPA_SCREENF = 5;  // завершающий пакет


procedure ListenThread(P:Pointer); stdcall;
var
  len, j, x, i:integer;
  ip:integer;
  bytes_recv:integer;
  buff: array [0..PEPPA_BUFLEN] of char;
  fd:TFDSet;
  t:timeval;
  pkt:PRawPkt;
  jpg:TJPEGImage;
  bmp:TBitmap;
  mem:TMemoryStream;
  temp:TMemoryStream;
begin
  if listen(server,$202)<>0 then writeln('error listen');
  len:=sizeof(client_addr);
//  x:=500;
//  setsockopt(server,SOL_SOCKET,SO_ACCEPTCONN,@x,SizeOf(x));
//  setsockopt(server,SOL_SOCKET,SO_RCVTIMEO,@x,SizeOf(x));
//  x:=0;
  t.tv_sec:=0;
  t.tv_usec:=500;
  Writeln('ListenThread Created');
  new(pkt);
  PktClear(pkt);
  jpg:=TJPEGImage.Create;
  bmp:=TBitmap.Create;
  mem:=TMemoryStream.Create;
  temp:=TMemoryStream.Create;
  while not quit do
  begin
   // Writeln('Listening');
    FD_ZERO(fd);
    FD_SET(server,fd);

    select(0,@fd,nil,nil,@t);

    if FD_ISSET(server,fd) then
    begin
      currsock:=accept(server,@client_addr,@len);

      if currsock <> invalid_socket then
      begin
        gethostbyaddr(@client_addr,len,AF_INET);
        ip:=client_addr.sin_addr.S_addr;

        writeln(ip and $FF,'.',(ip shr 8) and $FF,'.',(ip shr 16) and $FF,'.',(ip shr 24),':',client_addr.sin_port,' - connected');
      end;
    end;

    bytes_recv := recv(currsock, buff[0], PEPPA_BUFLEN, 0);
    j:=WSAGetLastError;

    if (j>0) and (j<=WSAECONNRESET) and (currsock <> -1) then
    begin
      Shutdown(currsock, SD_BOTH);
      closesocket(currsock);
      currsock:=-1;
      FillMemory(@buff[0],PEPPA_BUFLEN,0);
      Continue;
    end;

    if bytes_recv > 0 then
    begin
      Writeln('Received: ',Byte(buff[0]));

      case byte(buff[0]) of
        PEPPA_PING:
        begin
          PktClear(pkt);
          PktInt(pkt,PEPPA_PONG,1);
          SendPacket(pkt);
          Writeln(', sended pong (2)');
        end;

        PEPPA_SCREENN:
        begin
         { PktClear(pkt);
          PktInt(pkt, PEPPA_SCREENA, 1);
          CaptureScreen(bmp);
          jpg.Assign(bmp);
          mem.Clear;
          mem.Position:=0;
          jpg.SaveToStream(mem);
          mem.Position:=0; }

          //CaptureScreen(bmp);
          //jpg.Assign(bmp);
          jpg.LoadFromFile('sended.jpg');
          mem.clear;
          temp.Clear;
          jpg.SaveToStream(mem);
          mem.Position:=0;
          //mem.SaveToFile('sended_full.jpg');
          

          x:=round(mem.Size / PEPPA_BUFLEN)-1;
          for j:=0 to x do
          begin
            i:=mem.Read(buff[1],PEPPA_BUFLEN);
            Write(mem.position,'/',mem.Size,'   ',i,'   ',j,' / ',x);

            if j = 0 then
            begin
              buff[0]:=Char(PEPPA_SCREENN);
              Write('    START');
            end
            else
            begin
              if j=x//mem.position = mem.size
              then
              begin
                buff[0]:=Char(PEPPA_SCREENF);
                Write('    END');
              end
              else
              begin
                buff[0]:=Char(PEPPA_SCREENA);
                Write('    PART');
              end;
            end;

            write(#10);

            temp.Write(buff[1],i);
            temp.SaveToFile('sended'+_inttostr(j)+'.jpg');

            send(currsock, buff[0], i, 0);
          end;
          temp.SaveToFile('sended_full.jpg');

          //mem.read(pkt^.data[1], mem.Size);
          //SendPacket(pkt);
         // PktAddData(pkt, jpg);
          //jpg.SaveToStream(mem);
        end;

      end;
    end;

  end;
end;
Здравствуйте
NEoMASTERR вне форума Ответить с цитированием
Старый 14.10.2015, 16:50   #2
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию

Сервер передаёт пакеты по очереди, клиент бывает принимает их как попало

Клиент: (у учителя на пк)
Код:
procedure ReceiveThread(p:Pointer);
var
  buff:array [0..PEPPA_BUFLEN] of byte;
  fd:TFDSet;
  t:timeval;
  bytes_recv,j:integer;
  g:Cardinal;   
  jpg:TJPEGImage;
  bmp:TBitmap;
  lastreq:Cardinal;
begin
  Randomize;
 // if connstatus = 0 then Exit;
  t.tv_sec:=1;
  t.tv_usec:=0;

  buff[0] := 1;

  lastreq:=GetTickCount;
 // if connstatus <= 0 then OnConnectionFault(Self);
  while not quit do
  begin
    g:=GetTickCount;
    //connstatus:=send(sock,buff[0],1,0);
    FD_ZERO(fd);
    FD_SET(sock,fd);
    select(0,@fd,nil,nil,@t);
    if FD_ISSET(sock,fd) then
    begin
      FillMemory(@buff,PEPPA_BUFLEN, 0);
      bytes_recv := recv(sock, buff[0], PEPPA_BUFLEN, 0);

      //if bytes_recv = WSAEWOULDBLOCK then Sleep(1000);
      //j:=WSAGetLastError;
      if bytes_recv <> -1 then
      begin
        case buff[0] of
          PEPPA_PONG:
          begin
            g := GetTickCount - g;
            log('::Pong!:: '+inttostr(g)+'ms');
          end;
          PEPPA_SCREENN:
          begin
            counter:=0;
            pic.Clear;
            pic.Write(buff[1],bytes_recv);
            log('START Received '+inttostr(bytes_recv)+' bytes');
            //pic.SaveToFile('received.jpg');
          end;
          PEPPA_SCREENA:
          begin
            log('PART Received '+inttostr(bytes_recv)+' bytes');
            pic.Write(buff[1],bytes_recv);
            log(inttostr(pic.position));
            //pic.SaveToFile('received'+inttostr(counter)+'.jpg');
            inc(counter);
          end;
          PEPPA_SCREENF:
          begin
            log('END Received '+inttostr(bytes_recv)+' bytes');
            pic.Write(buff[1],bytes_recv);
            pic.Position:=0;
            jpg:=TJPEGImage.Create;
            jpg.LoadFromStream(pic);
            jpg.SaveToFile(ExtractFilePath(Application.ExeName)+'received_full.jpg');

            Form1.img1.Picture.Bitmap.Assign(jpg);
            pic.Clear;
            pic.Size:=0;
            jpg.Free;

            //buff[0] := PEPPA_SCREENN;
            //connstatus:=send(sock,buff[0],1,0);
          end;
        end;
      end;
    end;

   { if GetTickCount > lastreq then
    begin
      if pic.Size = 0 then
      begin
        buff[0] := PEPPA_SCREENN;
        connstatus:=send(sock,buff[0],1,0);
        lastreq:=GetTickCount+100;
      end;
    end;    }

  end;
end;
Переменная pic это глобальный TMemoryStream.
Заранее спасибо за помощь
Здравствуйте
NEoMASTERR вне форума Ответить с цитированием
Старый 14.10.2015, 17:00   #3
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию

Здравствуйте
NEoMASTERR вне форума Ответить с цитированием
Старый 14.10.2015, 17:54   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

В теме http://www.programmersforum.ru/showthread.php?t=282540 я давал примеры и ответы на некоторые душещипательные вопросы.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.10.2015, 18:11   #5
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
В теме http://www.programmersforum.ru/showthread.php?t=282540 я давал примеры и ответы на некоторые душещипательные вопросы.
Ничего не нашёл связанного с моим вопросом)
1. У вас компонент, у меня сокеты и {$APPTYPE CONSOLE}
2. У вас удп, у меня TCP
Здравствуйте
NEoMASTERR вне форума Ответить с цитированием
Старый 14.10.2015, 18:44   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Эхехех... Ладно. Не хочешь вникать - не надо. Пойдем от противного:
Цитата:
клиент бывает принимает их как попало
Про склейку пакетов слышал?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.10.2015, 18:51   #7
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Эхехех... Ладно. Не хочешь вникать - не надо. Пойдем от противного:

Про склейку пакетов слышал?
что то припоминаю но что именно - нет, с сокетами не так давно начал работать

Да и у меня буффер всегда одного размера, и заполняется полностью, и данных больше чем размер буфера мне не приходило, соответственно пакеты раздельно лежат (наверн)
Здравствуйте

Последний раз редактировалось Stilet; 14.10.2015 в 18:55.
NEoMASTERR вне форума Ответить с цитированием
Старый 14.10.2015, 19:00   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
соответственно пакеты раздельно лежат (наверн)
Я бы на это не надеялся.
Цитата:
что то припоминаю но что именно - нет
Если вкрадце: Существует проблема, когда recv() считывает не все что прислано сразу, а по мере отдачи от сетевушки (так сказать). Поэтому лично я рекомендую два способа определить что данные пришли:
1) Крутить считку в цикле, пока не закроется подкчение. Способ так себе, и при беспрерывной передаче морочный
2) Первыми 4-мя байтами я передаю кол-во передаваемых байтов в пакете. после в цикле считываю принятое, и анализирую сколько пришло. Считываемое помещаю конечно же в TMemoryStream для убодства. Как только кол-во считанного сравнится с сигнатурой размера из первых 4-х байт (integer которые) - передаю байты в картинку.
Цитата:
с сокетами не так давно начал работать
Можно узнать причину предпочтения сокетов?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.10.2015, 19:08   #9
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию

Попробую что нибудь сделать.

Интересно обходиться без готовых решений и компонентов. Да и вроде всё сетевое взаимодействие на них построено? не?
Здравствуйте
NEoMASTERR вне форума Ответить с цитированием
Старый 14.10.2015, 19:25   #10
NEoMASTERR
Форумчанин
 
Аватар для NEoMASTERR
 
Регистрация: 22.12.2010
Сообщений: 175
По умолчанию

И всё таки, если у меня все 20 пакетов одного размера, как же они склеиваются?
и второе, если я сделаю как вы сказали (размер данных указывать в пакете), то например параллельно с этим у меня придёт запрос на пинг, всё крашнется же.. Клиент посчитает что это картинка пришла.

Я всё еще не уверен что получится но спасибо за уделенное время
Здравствуйте
NEoMASTERR вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Jpeg warmbabe Общие вопросы по Java, Java SE, Kotlin 2 26.02.2010 20:14
Работа с JPEG Artruman Мультимедиа в Delphi 2 04.05.2009 15:13
jpeg.dcu Lemo Общие вопросы Delphi 14 31.12.2008 18:19
Jpeg Артэс Win Api 1 29.11.2008 08:48
jpeg All517 БД в Delphi 15 22.11.2007 14:31