Russian Qt Forum

Программирование => С/C++ => Тема начата: koldun90 от Октябрь 20, 2015, 20:40



Название: многопоточное копирование фала через сокет
Отправлено: koldun90 от Октябрь 20, 2015, 20:40
Здравствуйте есть клиент сервер
смысл в том что при подключении клиента к серверу(запускается отдельный) начинается копирование файла на сторону клиента
вопрос в следующем возможно ли сделать так чтобы если запустить одновременно много клиентов(допустим 10) файл копировался параллельно на все клиенты.

Во вложении проекты

код сервера

Код
C++ (Qt)
#include <QCoreApplication>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <fcntl.h>
#include <pthread.h>
#include <QFile>
#include <QTime>
pthread_mutex_t s;
int i=0;
void* potokfunc(void* ps)  //начало потока функция
{
   int desk=*(int *)ps;
   char buf[100];  //отправка номера размера имени файла
   char buf2[2048]; //отправка данных файла
   pthread_mutex_lock(&s);
   i=i+1;
   pthread_mutex_unlock(&s);
 
 
   // ОТПРАВЛЯЕМ НОМЕР ПАПКИ
   sprintf(buf,"%d",i);
   printf("НОМЕР ПАПКИ=%s\n",buf);
   //sleep(1);
   int rez=send(desk,buf,strlen(buf),0);
   if (rez>0)
   {
       printf("номер папки отправлен \n");
   }
 
   memset(buf,0,sizeof(buf));  // очищаем буфер
 
   //ОТПРАВЛЯЕМ РАЗМЕР ФАЙЛА
   QFile a("/qqq");
   int razmer;
   razmer=rez=a.size();
   char *razmert=QString::number(rez).toLocal8Bit().data();
   //sleep(3);
   sprintf(buf,"%s",razmert);
   printf("РАЗМЕР ФАЙЛА=%s\n",buf);
   rez=send(desk,buf,strlen(buf),0);
   if (rez>0)
   {
       printf("размер файла отправлен\n");
 
   }
   memset(buf,0,sizeof(buf));  // очищаем буфер
   //ОТПРАВЛЯЕМ ИМЯ ФАЙЛА
   sprintf(buf,"%s","/qqq");
   printf("ИМЯ ФАЙЛА=%s\n",buf);
   //sleep(3);
   rez=send(desk,buf,strlen(buf),0);
   if (rez>0)
   {
       printf("имя файла отправлено \n");
 
   }
   //sleep(2);
   FILE *f=fopen(buf,"rb");
   if (f!=NULL)
   {
 
       while(!feof(f))
       {
           rez=fread(buf2,1,sizeof(buf2),f);
           if (rez>0)  // если данные в буфер передали
           {
               rez=send(desk,buf2,strlen(buf2),0);
               if (rez>0)
               {
                   razmer=razmer-rez;
               }
               if (razmer==0)  //весь файл считали
               {
 
                   break;
               }
           }
       }
   }
 
   return NULL;
 
 
 
}
 
int main(int argc, char *argv[])
{
   pthread_mutex_init(&s,0);
   int fd=socket(AF_INET,SOCK_STREAM,0);
   if (fd<0)
   {
       printf("ощибка создания сокета");
       return 0;
   }
   struct sockaddr_in sockad;
   struct sockaddr_in klient;
 
   sockad.sin_addr.s_addr=htonl(INADDR_ANY);
   sockad.sin_family=AF_INET;
   sockad.sin_port=htons(6643);
 
   int rez=bind(fd,(struct sockaddr *)&sockad,sizeof(sockad));
   if (rez<0)
   {
       printf("ошибка привязки");
       return 0;
   }
   rez=listen(fd,1000);
   if (rez<0)
   {
       printf("не готово принимать соединения\n");
       return 0;
   }
   printf("сервер запущен\n ЖДУ ПОДКЛЮЧЕНИЙ\n");
 
   while (1)
   {
       int len=sizeof(klient);
       int fda=accept(fd,(sockaddr *)&sockad,(socklen_t *) &len);
       if (fda>0)  //если произошло соединение
       {
           printf("произошло подключение создаю поток\n");
           pthread_t tid;  //создали объект потока
           int jj=pthread_create(&tid, NULL, &potokfunc, &fda);    //передаем связный файловый дескриптор
           if (jj!=0)
           {
               printf("поток не создан\n");
           }
           sched_yield();
       }
   }
 
 
 
 
   return 0;
}
 


код клиента

Код
C++ (Qt)
#include <QCoreApplication>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <fcntl.h>
#include <pthread.h>
#include <QFile>
#include <QTime>
#include <QDir>
#include <stdio.h>
 
using namespace std;
 
int main(int argc, char *argv[])
{
   char buf[100];
   char buf2[2048];
   memset(buf,0,sizeof(buf));
   memset(buf2,0,sizeof(buf2));
 
   int fd=socket(AF_INET,SOCK_STREAM,0);
   if (fd<0)
   {
       printf("ощибка создания сокета\n");
 
   }
 
   struct sockaddr_in sock;
   sock.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
   sock.sin_port=htons(6643);
   sock.sin_family=AF_INET;
 
   int rez=connect(fd,(sockaddr *)&sock,sizeof(sock));
   if (rez<0)
   {
       printf("ошибка коннекта\n");
       return 0;
   }
   //принимаем номер папки
   rez=recv(fd,buf,sizeof(buf),0);
   if (rez>0)
   {
       cout<<"НОМЕР ПАПКИ="<<buf<<endl;
       printf("номер папки получен\n");
   }
 
 
   QString papka="/1000ARM/"+QString(buf);
   cout<<papka.toStdString()<<endl;
   QDir a;
   a.mkdir("/1000ARM");
 
   if (a.mkdir(papka)==true)
   {
       printf("папка создана\n");
   }
 
   memset(buf,0,sizeof(buf));
   int razmer;
   //принимаем размер файла
   rez=recv(fd,buf,sizeof(buf),0);
   if (rez>0)
   {
       razmer=QString(buf).toInt();
       cout<<"РАЗМЕР ФАЙЛА="<<buf<<endl;
       printf("размер файла получен\n");
   }
 
   memset(buf,0,sizeof(buf));
 
   rez=recv(fd,buf,sizeof(buf),0);
   if (rez>0)
   {
       cout<<"ИМЯ ФАЙЛА="<<buf<<endl;
       printf("имя файла получено\n");
   }
 
   QString imyaf=papka+QString(buf);
   char *im=imyaf.toLocal8Bit().data();
   FILE *f=fopen(im,"wb");
   printf("\n");
   if (f!=NULL)
   {
       while(1)
       {
           memset(buf2,0,sizeof(buf2));
           rez=recv(fd,buf2,sizeof(buf2),0);
           if (rez>0)  //если мы получили данные
           {
               printf("данные получены=%s\n",buf2);
               rez=fwrite(buf2,1,rez,f); //данные записаны
               if (rez>0)  //если мы записали данные
               {
                    printf("получено байт=%d\n",rez);
                   razmer=razmer-rez;
               }
               if (razmer==0)
               {
                   printf("весь файл принят\n");
                   break;
               }
           }
       }
   }
 
 
 
 
   return 0;
}
 
 
 


Название: Re: многопоточное копирование фала через сокет
Отправлено: Racheengel от Октябрь 21, 2015, 13:26
Конечно, можно. Сервер должен подключать каждого клиента отдельно (например, в отдельном потоке) и отдавать ему файл.


Название: Re: многопоточное копирование фала через сокет
Отправлено: koldun90 от Октябрь 21, 2015, 21:21
стоп я как раз так и сделал...
у меня после того как клиент присоединился выполняется функция потока
а как можно читать один и тот же файл допустим 10 потоками.
он будет корректно читаться?


Название: Re: многопоточное копирование фала через сокет
Отправлено: Bepec от Октябрь 21, 2015, 23:08
По идее вам нужно не читать файл десятью потоками, а читать одним и передавать десятью :)

PS это не то, что вы просите, но это примерно на 80% даст тот же результат.

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