Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > передача файлов через сеть


Автор: gabriil 20.8.2006, 13:10
вобщем я пишу прогу на языке СИ,цель  которой копиревать фаил с одного компа на другой.
проблема в том что программа работает на ура уменя на компютере,но когда прошу друга про тестить она отказывает.

вот мой сокет
socket(AF_INET, SOCK_STREAM, 0)

чтобы отослать фаил я открываю его так
fopen(c,"rb")

далее я записываю в массив 1024 байта,отсылаю его сайз а затем сам стринг 
send(l,c,sizeof©, 0)
между двомя отсылками стоит параметр слип.

затем ваил повторяется,до тех пор пока не дошел до EOF,затем посылается сайз остатка и сам остаток файла.

затем посылается "done" при виде которого клиент заканчивает принятие.

вот как я и говорил,уменя на машине всё работает,копирует любой фаил,но когда пытаюсь сделать тоже самое через сеть он принимает только четверть.
тоесть сервер говорит что отсылает 1024 байта а клиент принимает 0,каждый четвёртый стринг клиент принимает нормально.

у когонить есть понятие почему происходит такая каша?
 smile 

Автор: Romikgy 20.8.2006, 14:42
весь код в студию и клиента и сервера (сдобреного кнопачками "код")

Автор: gabriil 20.8.2006, 14:56
Код

   
//   ---------------------------------server------------------------------------------------

int main(int argc, char *argv[])
{
    int i,a,b,l,sin_size,yes=1;
  char c[1000];
  int chd,ps,ch,count,countt;
 char buffer[1024];
 long lSize;
 FILE *Fp;
 struct sockaddr_in my,th;
 time_t start_time, cur_time;
  
  
  
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2,1), &wsaData);
  
  if ((a = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
       {
            printf("\nError Socketing\n");
            exit(1);
        }

       /* if (setsockopt(a,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
            printf("\nError setcoket\n");
            exit(1);
        }*/
  
        my.sin_family = AF_INET;         
        my.sin_port = htons(MYPORT);    
        my.sin_addr.s_addr = INADDR_ANY;
        memset(&(my.sin_zero), '\0', 8); 
  
  if (bind(a, (struct sockaddr *)&my, sizeof(struct sockaddr))== -1) 
       {
         printf("\nError Binding\n");
            exit(1);
        }
  
   memset(c, '\0', 1000); 
  sin_size = sizeof(struct sockaddr_in);

  if (l = listen(a, BACKLOG) == -1)   
        { 
            printf("\nError\n");
            exit(1);
        }

   if((l = accept(a,(struct sockaddr *)&th,&sin_size)) == -1)
             {
              printf("Error");
              break;
             }      
             

      memset(c, '\0', sizeof(c)); // zero the rest of the struct
      if(((b = recv(l,c,sizeof(c)-1,0)) == -1)||(b == 0))
       {
        printf("\nError");
        break;
        }
        
        
                 if( strcmp(c,"copyf") == 0)
          {
              
             memset(c, '\0', sizeof(c)); 
             recv(l,c,sizeof(c)-1,0);               
                               
             if((Fp=fopen(c,"rb")) == NULL)
               {
                send(l,"error",5,0);                                
               }
             else
               {
                  
                  fseek (Fp , 0 , SEEK_END);
                  lSize = ftell (Fp);
                  rewind (Fp);
                  memset(c, '\0', sizeof(c));
                  itoa(lSize,c, 10);
                 if (send(l,c,sizeof(c), 0) == -1)
                  {
                   printf("Error Sending");
                   break;
                  }
                
                  memset(c, '\0', sizeof(c));
                  countt = 0;
                  count =0;
                  ch = 'h';
                 while(ch != EOF)//(countt < lSize)
                 {
                  count = 0;
                  memset(buffer,'\0',1024);
                    while((ch != EOF)&&(count < 1024))
                     {
                      ch=getc(Fp);
                      // if(countt < lSize)
                       // {
                           if(ch != EOF)
                           {
                         buffer[count] = ch;          
                         count++;
                         countt++;
                         }
                    
                         //}
                         //else
                         //break;
                          
                     }
                     
                  memset(c, '\0', 1000);
                  itoa(count,c, 10);
                   if (send(l,c,sizeof(c), 0) == -1)
                   {
                     printf("Error Sending");
                     break;
                   }
                  memset(c, '\0', 1000);
                     printf("send %dbytes\n",count);
                     sleep(35);
                     
                     if (send(l,buffer,sizeof(buffer), 0) == -1)
                       {
                        printf("Error Sending");
                        break;
                       }
                     memset(buffer,'\0',1024);   
                      sleep(35);               
                    } 
                    
                   memset(c, '\0', 1000);
                  itoa(4,c, 10);
                  if (send(l,c,sizeof(c), 0) == -1)
                {
                   printf("Error Sending");
                   break;
                }
                  memset(c, '\0', 1000);
                    
                   sleep(100);
       /*  time(&start_time);
         do
         {
                 time(&cur_time);
         }
         while((cur_time - start_time) < 2);*/

                 if (send(l,"done",4, 0) == -1)
                {
                   printf("Error Sending");
                   break;
                }
                printf("\ndone all");
              fclose (Fp);
             memset(buffer,'\0',1024);
              
               }
                               
          }
          
                closesocket(l);
   }
   



Код

//---------------------------------client-----------------------------------------------
int main(int argc, char *argv[])
{

  struct sockaddr_in th;
  int msg,a,b,l,sizes,sin_size,z,count,size,countt,cc;
  char ch,c[2000],com[1000],d[1000],read[1025],readd[1024];
   struct hostent *h;
   FILE *Fp;
   
   
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2,1), &wsaData);

    a = socket(AF_INET,SOCK_STREAM,0);
    memset(d,'\0',2000);
    
scanf("%s",&d);
h = gethostbyname(d);
 
 
 th.sin_family = AF_INET;   
     th.sin_port = htons(MYPORT);     
       th.sin_addr.s_addr = inet_addr(d);
        memset(&(th.sin_zero), '\0', 8); 

    connect(a, (struct sockaddr *)&th, sizeof(struct sockaddr));
   memset(com,'\0',1000);
      
      
          scanf("\n%s",com);
           
            if(strcmp(com,"copyf") == 0)
             {
          
                if(z = send(a, com, strlen(com), 0) == -1)
                 {
                  printf("\nData sent!");
                  break;
                 }
       
         printf("\nEnter The Name of file you want to copy (client.c) --- ");
        
         memset(com,'\0',1000);
          count =0;
               
               while(com[count-1] != 13)
                {
                    ch = getch();
                      if(ch != 8)
                         { 
                               com[count] = ch;      
                               printf("%c",com[count]);
                               count++;
                         }
                else
                { 
                  com[count] = ch;     
                  printf("%c",com[count]);     
                  printf("%c",32);
                  printf("%c",com[count]); 
                  count--;     
                 }
                }
                
                
                
      com[count-1] = '\0';
      
           if(z = send(a, com, strlen(com), 0) == -1)
            {
             printf("\nError Sending\nDisconecting\n");
             break;
            }
      
            memset(c,'\0',2000);
            recv(a,c,sizeof(c),0);
            if(strcmp(c,"error") != 0)
            { 
             size = atoi(c);
             memset(c,'\0',2000);
            
            
           
           
           memset(read,'\0',1025);
           
           countt = 0;
           strcat(com,".bak");
           
           Fp=fopen(com,"wb+");
           
          while( (strcmp(read,"done") != 0) && (strcmp(read,"error") != 0) )
          {
              memset(readd,'\0',1024);   
              
            if(((z = recv(a,readd,1024,0)) == -1)||(z == 0))
             {
              printf("\nError");
              break;
             }
            sizes = atoi(readd);
            printf("\n%d",sizes);
            memset(readd,'\0',1024);
              
              memset(read,'\0',1024);
            if(((z = recv(a,read,1025,0)) == -1)||(z == 0))
             {
              printf("\nError");
              break;
             }
           
                if((strcmp(read,"done") != 0)&&(strcmp(read,"error") != 0))
                 { 
                     cc=0;
                    /* while(cc < sizes)                  
                    {
                          putc( read[cc], Fp );
                          cc++;
                      }*/
                    // fprintf(Fp,"%s",read);        
                   countt = countt + 1;
                     fwrite (read , 1 , sizes , Fp);
               
               }
               else
               break;
             }
             
             if(countt == size)
              printf("\nok\n");
              else
              printf("/nerror/n");
             
               fclose(Fp);
               sizes = 0;
             }
            memset(c,'\0',sizeof(c)); 
           memset(com,'\0',sizeof(com));
           memset(read,'\0',1025);
                        
     }
     
     
   }
   
   


Автор: Romikgy 20.8.2006, 15:16
gabriil, в дальнейшем , если шлешь 2 файла потрудись их разбить на 2 кода, читать легче

Автор: Romikgy 20.8.2006, 15:36
имхо код написан корявенько 
нашел пару крупную ошибку
в клиенте 
Код

 memset(com,'\0',1000);    
          count =0;    
                
               while(com[count-1] != 13)    
                {    
                    ch = getch();    
                      if(ch != 8)    
                         {    
                               com[count] = ch;       
                               printf("%c",com[count]);    
                               count++;    
                         }    
                else    
                {    
                  com[count] = ch;      
                  printf("%c",com[count]);      
                  printf("%c",32);    
                  printf("%c",com[count]);    
                  count--;      
                 }    
                }    

знаешь че у тя будет при первом сравнении в while ?
и вообще отсылай все строки с завершающим 0 сзаду,
дабы потом проблем не было

Добавлено @ 15:37 
gabriil, уже краще smile

Автор: gabriil 20.8.2006, 15:58
а разве memset не обнуляет автоматом масив?

а тот кусочек кода это всеголишь принятие имени файла,эта ошибка не влияет на мою проблему.(наверное)
но я исправил спс.

а не аккуратно,это потомучто я полный наб.  smile 

а может быть чисто теоритически,какие проблемы могут быть в передачи через инет,которых не может быть в передачи на одном компе.
а вобще когджа запускаешь сервер и клиент на одном компе то нужно подключение к инету?

Автор: Romikgy 20.8.2006, 17:49
Цитата(gabriil @  20.8.2006,  14:58 Найти цитируемый пост)
а вобще когджа запускаешь сервер и клиент на одном компе то нужно подключение к инету?

нет

Цитата(gabriil @  20.8.2006,  14:58 Найти цитируемый пост)
а может быть чисто теоритически,какие проблемы могут быть в передачи через инет,которых не может быть в передачи на одном компе.

проблем может быть уйма, просто аккуратнее писать код надо, имхо как то делить по ф-циональности,
появлюсь дома еще раз код пересмотрю и протестю.

Кса у тя сервер одноразовый? один раз отдал файл и фсе?

Автор: gabriil 20.8.2006, 20:12
да хотябы один 
вобще мистика одна

Автор: Rockie 21.8.2006, 00:45
Цитата(gabriil @  20.8.2006,  13:10 Найти цитируемый пост)
проблема в том что программа работает на ура уменя на компютере,но когда прошу друга про тестить она отказывает.

что значит "отказывает"? пишет что не может найти dll/bpl?  или запускается и не работает.
Для певого случая:
Если компилятор BCB:
Project->Options->Linker снять галку use Dynamic RTL
Project->Options->Packajes->Build with runtime packajes снять галку
Project->Options->Compiler жмешь Release

Если компилятор VC то можно почитать http://forums.realcoding.net/lofiversion/index.php?t13011.html


Автор: gabriil 21.8.2006, 03:53
Цитата(Rockie @ 21.8.2006,  00:45)
Цитата(gabriil @  20.8.2006,  13:10 Найти цитируемый пост)
проблема в том что программа работает на ура уменя на компютере,но когда прошу друга про тестить она отказывает.

что значит "отказывает"? пишет что не может найти dll/bpl?  или запускается и не работает.
Для певого случая:
Если компилятор BCB:
Project->Options->Linker снять галку use Dynamic RTL
Project->Options->Packajes->Build with runtime packajes снять галку
Project->Options->Compiler жмешь Release

Если компилятор VC то можно почитать http://forums.realcoding.net/lofiversion/index.php?t13011.html

Цитата

вот как я и говорил,уменя на машине всё работает,копирует любой фаил,но когда пытаюсь сделать тоже самое через сеть он принимает только четверть.
тоесть сервер говорит что отсылает 1024 байта а клиент принимает 0,каждый четвёртый стринг клиент принимает нормально.

Автор: gabriil 21.8.2006, 04:20
прошу прощения!!!
не четверть!
с разными фалами по разному,если фаил маленький то примерно четверть,если больше то скакогото момента клиент начинает принимать место 1024 битов просто 24 бита.(каждая третея-четвёртая строка,остальные как и раньше НОЛЬ)

Автор: kirjanov 21.8.2006, 10:41
gabriil, 
вообще че-то не пойму,  ты тспользуешь SOCK_STREAM и UDP функциии. Ты лучше определись, UDP у тебя или TCP

Автор: Romikgy 21.8.2006, 11:00
Цитата(kirjanov @  21.8.2006,  09:41 Найти цитируемый пост)
UDP функциии

это где ?

Добавлено @ 11:05 
gabriil, 
попробуй покурить это
http://www.sources.ru/cpp/cpp_pb_sockets.shtml
а то у тя в коде слишком много ошибок , меня лично захарило править ошибки,
у мя теряются первые байты , где ты мешаешь и что делаешь типа размер передаешь и сами данные передаешь , это все может смешатся в кучу, так что кури выше приведеную ссылку

Автор: gabriil 21.8.2006, 12:25
Цитата(Romikgy @ 21.8.2006,  11:00)
Цитата(kirjanov @  21.8.2006,  09:41 Найти цитируемый пост)
UDP функциии

это где ?

Добавлено @ 11:05 
gabriil, 
попробуй покурить это
http://www.sources.ru/cpp/cpp_pb_sockets.shtml
а то у тя в коде слишком много ошибок , меня лично захарило править ошибки,
у мя теряются первые байты , где ты мешаешь и что делаешь типа размер передаешь и сами данные передаешь , это все может смешатся в кучу, так что кури выше приведеную ссылку

upd хз где,ткните пальцем я исправлю.


за ссылку спс,но к сожалению я понимаю только язык Си,всё что включает в себя "::" для меня дремучий лес.


а почему это может смешаться в кучу?

Автор: Romikgy 21.8.2006, 12:57
потому как вывод в сокет , имхо, действует наподобии вывода в файл , и вот если ты быстро передаешь и текст и данные , в разных send ' ах , они могут прийти и принятся одним recv smile так что надо или все в едином пакете кидать или выкручиватся по другому,
еще один вариант не передавать сразу весь файл и пусть сокет сам его фрагментирует smile

Добавлено @ 13:07 
Цитата(gabriil @  21.8.2006,  11:25 Найти цитируемый пост)
всё что включает в себя "::" для меня дремучий лес.

а выучить? smile

Автор: gabriil 21.8.2006, 13:21
Цитата(Romikgy @ 21.8.2006,  12:57)
потому как вывод в сокет , имхо, действует наподобии вывода в файл , и вот если ты быстро передаешь и текст и данные , в разных send ' ах , они могут прийти и принятся одним recv smile так что надо или все в едином пакете кидать или выкручиватся по другому,
еще один вариант не передавать сразу весь файл и пусть сокет сам его фрагментирует smile

Добавлено @ 13:07 
Цитата(gabriil @  21.8.2006,  11:25 Найти цитируемый пост)
всё что включает в себя "::" для меня дремучий лес.

а выучить? smile

уменя по этому поводу были соображения.чтобы избежать этой проблемы я поставил Слип.но также можно попробывать запросить от клиента конформацию получения,типо
сэнд размер - рисив конфармэйшин - сэнд стринг - рисив конфармэйшин.

также попробую передать фаил одним блоком,хотя не знаю как это возможно...
если фаил весит 10 мб то придётся аллокиревать массив на 10мб(это вобще можно?!),а если фаил весит 100мб?!

а нащёт выучить,дак вот учу пока Си,и так уже перешел с Борланд Си на Дев++,маюсь вторую неделю  без clrscr()  smile 

Автор: Romikgy 21.8.2006, 15:06
Цитата(gabriil @  21.8.2006,  12:21 Найти цитируемый пост)
а если фаил весит 100мб?!

при этом ты собираешься так файл читать?

Цитата(gabriil @  20.8.2006,  13:56 Найти цитируемый пост)
while((ch != EOF)&&(count < 1024))
                     {
                      ch=getc(Fp);
                      // if(countt < lSize)
                       // {
                           if(ch != EOF)
                           {
                         buffer[count] = ch;          
                         count++;
                         countt++;
                         }

ты хоть представляешь сколько он времени будет так читатся?
Цитата(gabriil @  21.8.2006,  12:21 Найти цитируемый пост)
это вобще можно?!

имхо можно главное что б у тя памяти хватило, или юзай файлы спроецированые в память

Цитата(gabriil @  21.8.2006,  12:21 Найти цитируемый пост)
Дев++

хорошая среда , но средства отладки там  smile 

Автор: ptr 21.8.2006, 15:41
recv возвращает только то, что есть в данный момент в буфере. Он конечно может быть и виноват.  Но проблема не в нём, а в криво написанном коде smile . gabriil, лучше перепиши программу заново, потому что из этой ничего хорошего не получится.

Цитата(gabriil @  21.8.2006,  17:21 Найти цитируемый пост)
чтобы избежать этой проблемы я поставил Слип.

Бесполезное решение.

Цитата(Romikgy @  21.8.2006,  16:57 Найти цитируемый пост)
так что надо или все в едином пакете кидать

А разница?

Цитата(Romikgy @  21.8.2006,  19:06 Найти цитируемый пост)
имхо можно главное что б у тя памяти хватило

Можно то можно, но нужно ли smile .

Автор: Romikgy 21.8.2006, 19:34
Цитата(ptr @  21.8.2006,  14:41 Найти цитируемый пост)

Можно то можно, но нужно ли 

от аффтара зависит
Цитата(ptr @  21.8.2006,  14:41 Найти цитируемый пост)
А разница?

разделять потом!

Автор: ptr 22.8.2006, 05:37
Цитата(Romikgy @  21.8.2006,  23:34 Найти цитируемый пост)
разделять потом!

Не понял. Потом это когда?

Автор: gabriil 22.8.2006, 07:32
ptr,я язык знаю совсем поверхностно,поетаму уменя средств подойти с другой стороны не так много.
где именно в этой программе чтото не так.
и это чтото не так,теоритически плохо или реализовано криво?

п.с. потОм или пОтом?  smile 

Автор: Romikgy 22.8.2006, 09:36
Цитата(ptr @  22.8.2006,  04:37 Найти цитируемый пост)
Не понял. Потом это когда? 

после приема

Автор: bel_nikita 22.8.2006, 09:40
Народ! Протокол FTP еще никто не отменял

Автор: ptr 22.8.2006, 12:09
Цитата(gabriil @  22.8.2006,  11:32 Найти цитируемый пост)
ptr,я язык знаю совсем поверхностно,поетаму уменя средств подойти с другой стороны не так много.

Ну а что тогда с сокетами связался.

Цитата(gabriil @  22.8.2006,  11:32 Найти цитируемый пост)
где именно в этой программе чтото не так.

Да везде.

Цитата(gabriil @  22.8.2006,  11:32 Найти цитируемый пост)
и это чтото не так,теоритически плохо или реализовано криво?

И то и другое.

gabriil, я могу поправить программы, но они будут сильно отличаться от того, что есть сейчас.

Цитата(Romikgy @  22.8.2006,  13:36 Найти цитируемый пост)
после приема 

Romikgy, я не то процитировал smile . Вот я про что:
Цитата(Romikgy @  21.8.2006,  16:57 Найти цитируемый пост)
еще один вариант не передавать сразу весь файл и пусть сокет сам его фрагментирует smile

Автор: gabriil 22.8.2006, 12:15
Цитата

Ну а что тогда с сокетами связался


с чегото начинать надо  smile 

Автор: ptr 22.8.2006, 12:23
Цитата(gabriil @  22.8.2006,  16:15 Найти цитируемый пост)
с чегото начинать надо  smile  

Сокеты - не лучший выбор.

Автор: Romikgy 22.8.2006, 12:26
Цитата(ptr @  22.8.2006,  11:09 Найти цитируемый пост)
Вот я про что:

и что не так?

Автор: ptr 22.8.2006, 15:00
Цитата(Romikgy @  22.8.2006,  16:26 Найти цитируемый пост)
и что не так? 

Да нет всё нормально. Только что это изменит?

Автор: Romikgy 22.8.2006, 15:03
Цитата(ptr @  22.8.2006,  14:00 Найти цитируемый пост)
 Только что это изменит?

ни ля ля не понял, дафай пополочкам, что и где изменит
(всю мысль давай,  а не частями)

Автор: ptr 22.8.2006, 15:17
Ладно проехали smile . Просто я хотел сказать, что нет особой разницы в том, как посылать файл - полностью или по частям. Точнее разница есть smile , но в данном случае это ничего не даст.

Автор: gabriil 22.8.2006, 20:13
Цитата

Ладно проехали  . Просто я хотел сказать, что нет особой разницы в том, как посылать файл - полностью или по частям. Точнее разница есть  , но в данном случае это ничего не даст.


почему это ничего не даст,где конкретно ошибка?
теоритически план пересылки распиши пожалуйста.

Цитата

Сокеты - не лучший выбор. 


а что лучше?
я изучил книгу дейтелов "как программиревать на Си" и в школе немного прошел.
сейчас считаю что пора начать работу с сетью,а затем переходить на функции виндуса.

Автор: Romikgy 23.8.2006, 10:00
Цитата(gabriil @  22.8.2006,  19:13 Найти цитируемый пост)
сейчас считаю что пора начать работу с сетью,а затем переходить на функции виндуса. 

имхо всегда делается наоборот

Цитата(gabriil @  22.8.2006,  19:13 Найти цитируемый пост)
а что лучше?


Цитата(bel_nikita @  22.8.2006,  08:40 Найти цитируемый пост)
Народ! Протокол FTP еще никто не отменял 

хотя он и сложнее

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)