Название: многопоточное копирование фала через сокет
Отправлено: 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 ну или можно сильно заморочиться, ввести хранилище хендлов на файлы или использовать неблокирующее чтение или кеширование. Но тут уже надо исходя из задачи выбирать.
|