Sockets
Чтоесть:
-программ сервер (принимает подключения от любого клиента на заданном порту, запоминает дескриптор сокета и ip клиента, далее ждет новых подключений)
-программа клиент(подключаеться по заданному порту и ip к серверу , реализован чат-могу принимать с сервера и отсылать сообщения на сервер)
Вопрос:
хочу передать с сервера на клиент определенный список файлов.Как быть? Сокет клиента известен. Дайте алгоритм так чтоб на клиент отсылалось имя файла и размер и само его содержимое. Как отослать все это с сервера проблем нет, но не получаеться реализовать прием и создание файлов на сокете.
Пример алгоритма
для сервера:
-поиск файла
-чтение имени файла и отправка клиенту
-чтение размера файла и отправка клтенту
-далее чтение файла по 1024 байта и отправка на клиент
-извещение о конче файла
-извещение о конце передачи файлов
для клиента:
-проверка на начало приема файлов с сервера
-прием имеи файла
-прием размера файла
-прием файла
-проверка размера созданного файла и с присланным размером
-если все ок, принимаем новый файл
-проверка на окончание передачи
Алгоритм для сервера работает безукоризненно, проверял все в дебагере, читает инфу из файла и отправляет то, что надо.
Но вот только файл который создаеться клиентом далек от оригинала. Не четко получаеться отследить приход нового сообщения с сервера(хоть на сервере и стоят приличные задержки).Вобщем как создать файл на клиенте с правильным именем это я сделал, как его теперь правильно заполнить??
Кто чем может помогите, подскажите, может более качественный алгоритм подскажете.Жду ваших ответов!!!!
Люди, помогите. Очень срочно нужно разобраться как реализовать передачу файлов через сокеты.
Чтоесть:
-программ сервер (принимает подключения от любого клиента на заданном порту, запоминает дескриптор сокета и ip клиента, далее ждет новых подключений)
-программа клиент(подключаеться по заданному порту и ip к серверу , реализован чат-могу принимать с сервера и отсылать сообщения на сервер)
Вопрос:
хочу передать с сервера на клиент определенный список файлов.Как быть? Сокет клиента известен. Дайте алгоритм так чтоб на клиент отсылалось имя файла и размер и само его содержимое. Как отослать все это с сервера проблем нет, но не получаеться реализовать прием и создание файлов на сокете.
Пример алгоритма
для сервера:
-поиск файла
-чтение имени файла и отправка клиенту
-чтение размера файла и отправка клтенту
-далее чтение файла по 1024 байта и отправка на клиент
-извещение о конче файла
-извещение о конце передачи файлов
для клиента:
-проверка на начало приема файлов с сервера
-прием имеи файла
-прием размера файла
-прием файла
-проверка размера созданного файла и с присланным размером
-если все ок, принимаем новый файл
-проверка на окончание передачи
Алгоритм для сервера работает безукоризненно, проверял все в дебагере, читает инфу из файла и отправляет то, что надо.
Но вот только файл который создаеться клиентом далек от оригинала. Не четко получаеться отследить приход нового сообщения с сервера(хоть на сервере и стоят приличные задержки).Вобщем как создать файл на клиенте с правильным именем это я сделал, как его теперь правильно заполнить??
Кто чем может помогите, подскажите, может более качественный алгоритм подскажете.Жду ваших ответов!!!
Для этого клиент должен запросить у сервера необходимый файл.
Посылает запрос серверу.
Сервер получает запрос.
Сервер отвечает что начат поиск файла.
Ищет файл.
Клиент получает ответ что поиск начат.
Цикл
Клиент Посылает уведомление о готовности принять файл.
Сервер уведомляет о текущем статусе.
Если поиск закончен - посылка уведомления на клиента и выход из цикла.
Делать пока поиск не закончен или клиент не послал уведомление - прервать.
Клиент - если ответ положительный - запрос начала предачи.
Сервер посылает размер файла.
Клиент - если размер совпадает - готов.
Сервер отправляет порцию.
Клиент при получении - подтверждение.
Сервер достиг конца файла - завершение предачи.
Клиент - сохранение файла на диск.
Завершение соединения.
Инициатором в обмене всегда должен быть клиент. Если необходимо что бы сервер слал данные на клиента прямо - тогда каждый из них должен быть и клиентом и сервером.
Для этого клиент должен запросить у сервера необходимый файл.
Посылает запрос серверу.
Сервер получает запрос.
Сервер отвечает что начат поиск файла.
Ищет файл.
Клиент получает ответ что поиск начат.
Цикл
Клиент Посылает уведомление о готовности принять файл.
Сервер уведомляет о текущем статусе.
Если поиск закончен - посылка уведомления на клиента и выход из цикла.
Делать пока поиск не закончен или клиент не послал уведомление - прервать.
Клиент - если ответ положительный - запрос начала предачи.
Сервер посылает размер файла.
Клиент - если размер совпадает - готов.
Сервер отправляет порцию.
Клиент при получении - подтверждение.
Сервер достиг конца файла - завершение предачи.
Клиент - сохранение файла на диск.
Завершение соединения.
Инициатором в обмене всегда должен быть клиент. Если необходимо что бы сервер слал данные на клиента прямо - тогда каждый из них должен быть и клиентом и сервером.
вобщем не совсем так, я просидев всю ночь разобрался как это сделать и сделал.
Дело в том что я пишу клиент и сервер для упрощения запуска программ написанных с помощью MPI. Роль сервера - определение ресурсов сети(проще говоря смотрит сколько компов к нему подключено, сравнивает с тем что нужно в задачи, если все ок, рассылает по клиеттам MPI проэкт, определяет параметры запуска,т.е. на каком компе и сколько процессов будет запущено). Роль клиента-прием проэкта, запуск его на сети по команде с сервера, мониторинг выполнения проэкта, по окончании если есть результаты в виде файлов, то файлы переименовываються и каждым клиентом в отдельности присылаються сасервер.
Вот как я реализовал свой алгоритм(про который я спрашивал в первом сообщении)
сервер:
-запуск процедуры поиска файлов
-если есть файл кидаем на клиент уведомление: StartSend
-далее кидаем имя файла
-размер файла
-читаем файл по 1024 бита и отправляем
-как достигаем конца кидаем уведомление StopSend
-поиск нового файла, если есть , то цикл
/*уведомление в моем случае просто AnsiString зарезервированные на сервере ина клиенте, и на клиенте они отслеживаються*/
клиет:
-проверка на уведомление, если оно есть, то цикл пока не будет уведомления конца файла
-читаем первое сообщение-имя файла, открывае файл для записи
-читаем второе сообщение-размер файла, сохраняем
-цикл для приемафайла:
-проверка на приход сообщения в буфер
-читаем буфер
-пишем в файл
-сравниваем размер файла текущий с тем что получили
-коррекция (т.к. буфер 1024, то и запись в файл идет по 1024, поэтому последний блок полюбому корректируеться)
-если все прошло без ошибок то придет уведомление о конче передачи файла иначе вылетаю
Вся моя проблема заключалась в том что я не понимал как отследить изменения в буфере. Но после тщательного изучения справки си билдера меня осенило и на седьмой раз я код правильно написал, протестил, ошибок нет.
А вот что меня спасло:
if ( (nsize=recv(my_sock,&buff[0],1024,0))==-1 )
дело в том что выход из этого тфа будет только если в буфер что-то придет или пти отключении соединения-> nsize=-1; длина буфера=-1
а также при его переполнении помоему.
Если кому интересно пишите на форуме я выложу, правда я пока еще не дописал прогу, но уже результат не за горами.
Люди, помогите...
Я недавно мучался с пересылкой файла по сети, исспользовал TClientSocket и TServerSocket. Я заметим что хоть и сервер отправляет по 1024 байта, но клиент принимает всегда по разному от 500 (с чем-то) до 13784 байт, я исспользовал TWinSocketStream чтобы всегда знать сколько байт пришло и из своего буфера, размером 13784, в который я записывал байты из сокета, я записывал в файл столько, сколько вернула функция TWinSocketStream->Write.
А вообще выложи код отправки на сервере и приема на клиенте. Только не надо выкладвать простыню на 20 срт. выложи самое главное.
Я недавно мучался с пересылкой файла по сети, исспользовал TClientSocket и TServerSocket. Я заметим что хоть и сервер отправляет по 1024 байта, но клиент принимает всегда по разному от 500 (с чем-то) до 13784 байт, я исспользовал TWinSocketStream чтобы всегда знать сколько байт пришло и из своего буфера, размером 13784, в который я записывал байты из сокета, я записывал в файл столько, сколько вернула функция TWinSocketStream->Write.
А вообще выложи код отправки на сервере и приема на клиенте. Только не надо выкладвать простыню на 20 срт. выложи самое главное.
ну не на 20 поменьше ndesc-номер в таблице куда я вывожу ip и дескриптор сокета
для сервера:
{
my_sock=StrToInt(MainForm->ClientSendF->Cells[1][ndesc]);
int f;
TSearchRec sr;
f=FindFirst(buf.c_str(),faAnyFile,sr);
f=FindNext(sr);
f=FindNext(sr);
FILE* in;
if(f==0)
{
}
while (f==0)
{
//----Старт---------------
gettime(&t);
MainForm->ServiceInf->Items->Add("---------------------------------------------------------------------------");
MainForm->ServiceInf->Items->Add(Time+MainForm->ClientSendF->Cells[0][ndesc]+" --- "+sSTART);
send(my_sock,sSTART,sizeof(sSTART),0);
SendMessage(MainForm->ServiceInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->ServiceInf->Refresh();
gettime(&t);
//------Имя-------------------------
memset(buff, 0, 1024);
size=strlen(AnsiString(sr.Name).c_str());
for (i=0;i<size;i++)
buff=sr.Name[i+1];
size++;
buff='\0';
MainForm->ServiceInf->Items->Add(Time+sr.Name);//sr.Name
send(my_sock,&buff[0],size,0);
SendMessage(MainForm->ServiceInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->ServiceInf->Refresh();
//-------Размер------------------------
memset(buff, 0, 1024);
size=strlen(AnsiString(sr.Size).c_str());
for (i=0;i<size;i++)
buff=AnsiString(sr.Size).c_str();
size++;
buff='\0';
MainForm->ServiceInf->Items->Add(Time+sr.Size);//sr.Name
send(my_sock,&buff[0],size,0);
SendMessage(MainForm->ServiceInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
//-------Файл------------------------------
buf=patch+sr.Name;
in=fopen(buf.c_str(), "rb");
fgetc(in);
//читаем по 1024 байта и передаем
i=0;
fseek(in,SEEK_SET,0);
size=1024;
while (!feof(in))
{
memset(buff, 0, 1024);
fread(buff,1,1024, in);
send(my_sock,&buff[0],size,0);
//gettime(&t);
buf="";
for (i=0;i<1024;i++)
buf=buf+buff;
}
fclose(in);
MainForm->TextInf->Items->SaveToFile("Textinf.txt");
//-------Конец передачи------------
MainForm->ServiceInf->Items->Add(Time+Time+MainForm->ClientSendF->Cells[0][ndesc]+" --- "+sStop);//sr.Name
send(my_sock,sStop,sizeof(sStop),0);
SendMessage(MainForm->ServiceInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->ServiceInf->Refresh();
Sleep(10);
//---------------------------------
buf=patch+"*.*";
f=FindNext(sr);
}
FindClose(sr);
ndesc--;
}
Я недавно мучался с пересылкой файла по сети, исспользовал TClientSocket и TServerSocket. Я заметим что хоть и сервер отправляет по 1024 байта, но клиент принимает всегда по разному от 500 (с чем-то) до 13784 байт, я исспользовал TWinSocketStream чтобы всегда знать сколько байт пришло и из своего буфера, размером 13784, в который я записывал байты из сокета, я записывал в файл столько, сколько вернула функция TWinSocketStream->Write.
А вообще выложи код отправки на сервере и приема на клиенте. Только не надо выкладвать простыню на 20 срт. выложи самое главное.
а вот код для клиента:
int fs,i;
FILE* in;
bool stop=false;
bool end=false;
while( conn==true )
{
if ( (nsize=recv(my_sock,&buff[0],1024,0))==-1 )
goto err;
// ставим завершающий ноль в конце строки
buff[nsize]=0;
// выводим на экран
if (nsize>0)
{
if (AnsiString(buff)==sHELLO)
{
MainForm->TextSend->Enabled=true;
MainForm->ButSend->Enabled=true;
gettime(&t);
MainForm->TextInf->Items->Add(Time+"Успешное соединение с сервером");
SendMessage(MainForm->TextInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->TextInf->Refresh();
memset(buff, 0, 1024);
}
if (AnsiString(buff)==sQUIT)
{
gettime(&t);
MainForm->TextInf->Items->Add(Time+"Сервер закрыл подключение");
SendMessage(MainForm->TextInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->TextInf->Refresh();
MainForm->ClientEndClick(NULL);
memset(buff, 0, 1024);
}
i=0;
if (AnsiString(buff)==sSTART)
{
while(stop==false)
{
if ( (nsize=recv(my_sock,&buff[0],1024,0))==-1 )
goto err;
if(AnsiString(buff)==sSTOP)
{
stop=true;
gettime(&t);
MainForm->TextInf->Items->Add(Time+"Файл принят");
MainForm->TextInf->Items->Add("-------------------------------------------------------------");
SendMessage(MainForm->TextInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->TextInf->Refresh();
i=0;
fclose(in);
}
else
{
i++;
if(i==1 || i==2)
{ if (i==1)
{
gettime(&t);
MainForm->TextInf->Items->Add(Time+"Новый файл "+AnsiString(buff));
SendMessage(MainForm->TextInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->TextInf->Refresh();
in=fopen(AnsiString(buff).c_str(),"wb");
memset(buff, 0, 1024);
}
if (i==2)
{
filesize=StrToInt(buff);
gettime(&t);
MainForm->TextInf->Items->Add(Time+"Размер файла "+AnsiString(filesize));
SendMessage(MainForm->TextInf->Handle, WM_VSCROLL, MAKEWORD(SB_BOTTOM, 0), 0);
MainForm->TextInf->Refresh();
size=0;
}
}
else
{ if(filesize-size<nsize)
nsize=filesize-size;
size=size+nsize;
fwrite(buff,nsize,1,in);
}
}
}
stop=false;
}
}
}
err:
Я недавно мучался с пересылкой файла по сети, исспользовал TClientSocket и TServerSocket. Я заметим что хоть и сервер отправляет по 1024 байта, но клиент принимает всегда по разному от 500 (с чем-то) до 13784 байт, я исспользовал TWinSocketStream чтобы всегда знать сколько байт пришло и из своего буфера, размером 13784, в который я записывал байты из сокета, я записывал в файл столько, сколько вернула функция TWinSocketStream->Write.
А вообще выложи код отправки на сервере и приема на клиенте. Только не надо выкладвать простыню на 20 срт. выложи самое главное.
С этим я не сталкивался,у меня буфер зафиксирован на 1024 и проблем нет, только надо следить за тем чтоб при приеме файла последний пакет нужно подредактировать.
Код который я выложил для моей задачи рабочий, правда если в папке где идет поиск файлов нет подпапок.
Спасибо за интерес к моему коду, надеюсь поможет, я сам долго возился пока разобрался !! :)
С этим я не сталкивался,у меня буфер зафиксирован на 1024 и проблем нет, только надо следить за тем чтоб при приеме файла последний пакет нужно подредактировать.
Код который я выложил для моей задачи рабочий, правда если в папке где идет поиск файлов нет подпапок.
Спасибо за интерес к моему коду, надеюсь поможет, я сам долго возился пока разобрался !! :)
АММ, во что хочу добавить. Вообще эта вся бодяга-часть моей дипломной работы. Эти кусочки что я выложил далеко не лучший вариант! ПОЧЕМУ???
Ответ прост.
Тестил я свою прогу: включил удаленный доступ к другому компу, запустил клиента. Проги сконектились, асдрес и размер первого файла переслались и принялись на обеих сторонах без проблем, НО САМ ФАЙЛ-сплошной глюк? почему? Как я выяснил некоторые пакеты всетаки могут теряться в том случае когда канал связи забит сильно, это раз, если компутер вторй слабенький это два. В первом случае я думаю и так ясно в чем дело, а во втором медленный компутер тот же самый цикл просто делает за дольшее время и пакеты не успевает обработать.
Как тут мона поступись.
На первый взгляд можно воткнуть задержки между отправками, но реально это бред. Представьте: у вас трафик нулевой, компы мощный один другому килобит кинет, и что-то ждет-трата времени бесмыслена! решение простое: отправил ты килобит клиенту(серверу-не суть важно) жди уведомления, которое ты конечно заранее пропишешь, тогда во-первых-трафик используется (на сколько может это сам алгоритм программы позволить) по максимуму, а во вторых-уведомление-гарантия доставки пакета. Т.е. ни куда уже твой файл не исчезнет и абра-кадабра не получится!
Позже выложу нормальные коды, а пока пользутесь тем что есть.
Если вам это помогло, очень рад, что мой труд кому-то поможет!
Всем удачи! Рулите тему дальше! Оставляйте коменты!
... НО САМ ФАЙЛ-сплошной глюк? почему? Как я выяснил некоторые пакеты всетаки могут теряться ...
Если не ошибаюсь, то за то, чтобы пакеты не терялись отвечает протокол TCP\IP. Проверь, может ты из сокета длину буфера не правильно читаешь, или в файл не буфер не той длины записываешь, или еще что-то...
Но пакеты не могут просто так теряться, это не UDP какой-нибудь. Хотя я не проф, могу ошибаться, так что не судите строго...
Если не ошибаюсь, то за то, чтобы пакеты не терялись отвечает протокол TCP\IP. Проверь, может ты из сокета длину буфера не правильно читаешь, или в файл не буфер не той длины записываешь, или еще что-то...
Но пакеты не могут просто так теряться, это не UDP какой-нибудь. Хотя я не проф, могу ошибаться, так что не судите строго...
Прежде чем читать данные из сокета - необходимо получать размер переданных данных и читать до тех пор пока размер прочитанных не соответствует размеру переданных. Протокол ТСР (и только ТСР) гарантирует доставку пакетов. Никаких гарантий что, ВСЕ данные, которые отправленные приложением будут получены другим приложением протокол не дает. Единственная гарантия - что все ПОЛУЧЕННЫЕ пакеты пришли в правильном порядке и не испорчены.
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
AnsiString C_Path = "C:\\CHAT\\" + ExtractFileName(AThread->Connection->ReadLn());
TFileStream *f;
if(!FileExists(C_Path)){
f = new TFileStream(C_Path,fmCreate);
}
else
{
f = new TFileStream(C_Path,fmOpenWrite);
}
AThread->Connection->ReadStream(f,-1,true);
delete f;
}
На клиенте отправляем:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString S;
if(OpenDialog1->Execute()){
try{
IdTCPClient1->Connect();
IdTCPClient1->WriteLn(OpenDialog1->FileName);
TFileStream *f = new TFileStream(OpenDialog1->FileName,fmOpenRead);
Screen->Cursor = crHourGlass;
IdTCPClient1->OpenWriteBuffer();
IdTCPClient1->WriteStream(f,true,true);
Screen->Cursor = crDefault;
IdTCPClient1->CloseWriteBuffer();
delete f;
IdTCPClient1->Disconnect();
}
catch(...)
{
ShowMessage("Не удалось отправить файл. Возможно серверный компьютер отключен");
return;
}
S = ExtractFileName(OpenDialog1->FileName);
ShowMessage("Файл " +S+ "выложен в папку CHAT серверного компьютера");
}
}
...Протокол ТСР (и только ТСР) гарантирует доставку пакетов. Никаких гарантий что, ВСЕ данные, которые отправленные приложением будут получены другим приложением протокол не дает. Единственная гарантия - что все ПОЛУЧЕННЫЕ пакеты пришли в правильном порядке и не испорчены.
Я че-то не понял что значит TCP гарантирует доставку пакетов, гарантирует последовательность и содержание пакетов, но не гарантирует что все данные будут получены... Так он все таки гарантирует или не гарантирует, на сколько мне известно гарантирует.
Я че-то не понял что значит TCP гарантирует доставку пакетов, гарантирует последовательность и содержание пакетов, но не гарантирует что все данные будут получены... Так он все таки гарантирует или не гарантирует, на сколько мне известно гарантирует.
Протокол гарантирует, что пакеты ПОЛУЧЕННЫЕ принимающей программой - будут получены в надлежайшем порядке и не испорчены. Допустим некое приложение отправило десять пакетов с порядковыми номерами от одного(это к примеру) до десяти(). Так вот вы можете быть уверены что если другое приложение приняло только ТРИ из них - допустим 3,5 и 7 - то приймет оно их в надлежащем порядке и целыми - и не более чем. Доставку всех 10 пакетов протокол н е г а р а н т и р у е т. Это ваша задача проверять целостность переданных данных. Пример конечно жесткий - но на самом деле надо понимать, в чем вы можете доверять протоколу - а что вы обязаны проверить.
Я че-то не понял что значит TCP гарантирует доставку пакетов, гарантирует последовательность и содержание пакетов, но не гарантирует что все данные будут получены... Так он все таки гарантирует или не гарантирует, на сколько мне известно гарантирует.
Кстати как ТСР может гарантировать доставку пакетов? И где это описано? Гарантируется получение целого пакета - но не гарантируется что ВСЕ пакеты будут доставлены. Простой эксперемент можно поставить если сети соеденены через несколько свичей - попробуйте слать файл достаточно большого размера и поэксперементируйте выключая часть свичей. Как правило в большой сети(это важно) 20-30(из 10000 примерно) пакетов не дойдут. (По крайней мере в моих эксперементах было так - причем если коннект прямой - ошибка ловилась сразу(ошибка записи в сокет, что вобщемто не удивительно))
Всем привет и респект! Народ извините за оффтоп, но помогите плиз начинающему программисту: не могу найти мануал по winsock для C++ Builder, подскажите кто нить чтонибудь, неважно на каком языке, главное чтобы доступно и с примерами! Также если знаете хорошие материал по Win32Api кидайте ссылки! Заранее балгодарен!!!
Вот ссылка на все случаи жизни
ЗЫ “Времена не выбирают...” написал А. Кушнер. Не надо плодить новые мифы.
Прежде чем читать данные из сокета - необходимо получать размер переданных данных и читать до тех пор пока размер прочитанных не соответствует размеру переданных. Протокол ТСР (и только ТСР) гарантирует доставку пакетов. Никаких гарантий что, ВСЕ данные, которые отправленные приложением будут получены другим приложением протокол не дает. Единственная гарантия - что все ПОЛУЧЕННЫЕ пакеты пришли в правильном порядке и не испорчены.
Вот тут один момент!!!!
Если вы не заметили, то повторюсь!!! Размеры пакетов у меня фиксированы!!! по 1024б !! поэтому определять размер пакета во время приема файлов мне не надо-это раз!
Второе размер файла я отправляю не случайно!!!
Если создать файл и все время в него записывать принятые пакеты, то файл получиться разбером больше, чем должен быть!!! и при этом кратным 1024!!
Поэтому последний пакет записываеться в файл не полностью!! А именно та часть пакета, которая необходима.
пример пердаю файл размером 1026 б
1)передаю размер файла, начинаю пересылаьб файл
2)принимаю первый пакет(до этого я уже принял размер файла) полностью -1024
3)анализирую размер:
1026-1024*i=2 (i-счетчик пакетов, на данном этапе принят один пакет i=1)
размер нового пакета болжен быть равен 2!!!
Но пакет принимаю размером 1024 и в файл записываю только первые 2b.
вот и вся идея!
Вот тут один момент!!!!
Если вы не заметили, то повторюсь!!! Размеры пакетов у меня фиксированы!!! по 1024б !! поэтому определять размер пакета во время приема файлов мне не надо-это раз!
это ты IP протоколу расскажи. если ты передаешь через сеть с маленьким MTU, пакеты будут дробится. это раз. во-вторых проткол НЕ гарантирует доставку данных. ты можешь передать 1024 байта, а дойдут 1000. поэтому на уровне программы контролировать надо - явно пересылать размер файла и т. п.
Кстати как ТСР может гарантировать доставку пакетов? И где это описано? Гарантируется получение целого пакета - но не гарантируется что ВСЕ пакеты будут доставлены. Простой эксперемент можно поставить если сети соеденены через несколько свичей - попробуйте слать файл достаточно большого размера и поэксперементируйте выключая часть свичей. Как правило в большой сети(это важно) 20-30(из 10000 примерно) пакетов не дойдут. (По крайней мере в моих эксперементах было так - причем если коннект прямой - ошибка ловилась сразу(ошибка записи в сокет, что вобщемто не удивительно))
Тут я согласен, НО!!! Экспериментально выяснил одну очень хорошую вещь!!!
Да TCP\IP не гарантирует доставку всех пакетов, НО, это можно исправить: как я выяснил(могу ошибаться) пакеты не теряются, если сеть свободна, либо трафик слабый, но как только сеть загружается, то пакеты через один пропадают-выход-уменьшить частоту отправки пакетов и сделать уведомления:
кинул пакет- ждеш уведомления
на другой стороне принял пакет- сразу кинул уведомление
В этом случае пакеты не исчезают, Но :D столкнулся с такой вещью, что отправленное уведомление приходит раньше, чем начинаеться проверка на уведомление- в результате зависаем-ждем уведомление, которое уже проскочило!!!
это ты IP протоколу расскажи. если ты передаешь через сеть с маленьким MTU, пакеты будут дробится. это раз. во-вторых проткол НЕ гарантирует доставку данных. ты можешь передать 1024 байта, а дойдут 1000. поэтому на уровне программы контролировать надо - явно пересылать размер файла и т. п.
:)) с этим проблем у меня нет, я пишу узко специализированный програмный комплекс под определенную сеть, хотя я и на других сетях тестил и у себя дома, настолько маленьких MTU пока не встречал, прога пишеться под 100 мегабитные сети, а там mtu достаточного размера.
Тут я согласен, НО!!! Экспериментально выяснил одну очень хорошую вещь!!!
Да TCP\IP не гарантирует доставку всех пакетов, НО, это можно исправить: как я выяснил(могу ошибаться) пакеты не теряются, если сеть свободна, либо трафик слабый, но как только сеть загружается, то пакеты через один пропадают-выход-уменьшить частоту отправки пакетов и сделать уведомления:
кинул пакет- ждеш уведомления
на другой стороне принял пакет- сразу кинул уведомление
В этом случае пакеты не исчезают, Но :D столкнулся с такой вещью, что отправленное уведомление приходит раньше, чем начинаеться проверка на уведомление- в результате зависаем-ждем уведомление, которое уже проскочило!!!
ййэххх... народ... опять велосипед изобретаем.
ййэххх... народ... опять велосипед изобретаем.
Дело тут не в том изобретаем или нет, еслиб хоть гдето было что-то толком написано!!!
Причем не все сразу становяться специалистами, пока сам с этим не повозишся, тонкости все не прочувствуеш, далеко не уедеш, а как сам начинаеш ручками работать, да извилину напрягать-тут и идеи новые рождаются.
Дело тут не в том изобретаем или нет, еслиб хоть гдето было что-то толком написано!!!
Причем не все сразу становяться специалистами, пока сам с этим не повозишся, тонкости все не прочувствуеш, далеко не уедеш, а как сам начинаеш ручками работать, да извилину напрягать-тут и идеи новые рождаются.
Изобретаем, изобретаем.
А на счет того что почитать - так все зависит от того что ты читаешь. Конечно, если занимаешься изобретением велосипеда - так читать просто некогда - проблем кучи встают :) а если еще и это самое изобретение через ж... делать - тогда совсем уж дел невпроворот :)
Или толком написано - это разжевано и врот положено? Тогда действительно читать нечего. Ибо детям спички не игрушка.
З.Ы. Не обижайся. Все что поможет тебе в решении проблемы написано в предыдущих постах. Если ты попрежнему считаешь что размер пакета у тебя определен и задача у тебя настолько узко специализирована, что за 40 лет практического развития сетей ее никто не решал - ну тогда извини. Код писать за тебя никто не будет.
Дело тут не в том изобретаем или нет, еслиб хоть гдето было что-то толком написано!!!
Причем не все сразу становяться специалистами, пока сам с этим не повозишся, тонкости все не прочувствуеш, далеко не уедеш, а как сам начинаеш ручками работать, да извилину напрягать-тут и идеи новые рождаются.
толком - советую найти книгу Йона Снейдера "Эффективное программирование TCP/IP". у него одна глава просто таки списана с твоей проблемы :)
удачи.
З.Ы. Упс...опередили :)
На этом форуме уже упоминалась книга "Эффективное программирование ТСР/ІР" - гдето попадалась и в єлектронном виде - начни с нее. Может быть тогда целый ряд вопросов будет формулироваться у тебя совсем по другому. Ну и поиск в том же гугле никто не отменял.
З.Ы. Упс...опередили :)
:))) я ее в каждом топике упоминаю
:))) я ее в каждом топике упоминаю
Ты хочешь сказать, что это единственная книга которую ты читал? ;););)
Шучу.
На этом форуме уже упоминалась книга "Эффективное программирование ТСР/ІР" - гдето попадалась и в єлектронном виде - начни с нее. Может быть тогда целый ряд вопросов будет формулироваться у тебя совсем по другому. Ну и поиск в том же гугле никто не отменял.
З.Ы. Упс...опередили :)
ООО, спасибо за литературу!!! А кому интересно, те могут найти эту книгу по этой ссылке
http://www.internet-technologies.ru/books/book_103.html
Около 7 Мб
Если можете, посоветуйте еще что-нибудь по сокетам!!!(Желательно, чтоб это можно в нете скачать)
ООО, спасибо за литературу!!! А кому интересно, те могут найти эту книгу по этой ссылке
http://www.internet-technologies.ru/books/book_103.html
Около 7 Мб
Если можете, посоветуйте еще что-нибудь по сокетам!!!(Желательно, чтоб это можно в нете скачать)
еще могу порекомендовать книгу Стивенса "Разработка сетвых приложений". я ее качал на Natahaus, по моему. если не найдешь - отпиши в личку, выложу дома на FTP.
в качестве теории - третий том из серии учебников по TCP/IP Комера. этот том есть в трех вариантах - для UNIX (сокеты Беркли), Windows (Winsock) и TLI
в качестве теории - третий том из серии учебников по TCP/IP Комера. этот том есть в трех вариантах - для UNIX (сокеты Беркли), Windows (Winsock) и TLI
Как кстати? Я на него поглядываю - все не соберусь купить - стоит? Может у тебя есть в електронке?
Как кстати? Я на него поглядываю - все не соберусь купить - стоит? Может у тебя есть в електронке?
я купил первый и третий. второго почему то не издали :) доволен. кое что устарело, конечно, но теоретическая база капитальная.
Если все-таки кто увидит какие Баги просьба сообщить.
Основное отличие от того что было:
Добавлены отчеты: теперь нет ни каких глюков- сообщения идут синхронно!
Смотрите коды ниже:
Все время получаю сообщение "Can't connect"? Пробовал разные хосты, даже в локалке, все равно не пашет. Помогите плиз.
struct sockaddr_in srv;
struct hostent* ip_addr;
int port,s;
char ip;
char* http_host="ya.ru";
if (WSAStartup(WINSOCK_VERSION, &wsaData)) {ShowMessage("Can't Initialize");return 0;}
ip_addr=gethostbyname(http_host);
if (!ip_addr) {ShowMessage("Can't Resolve Hostname");return 0;}
srv.sin_family=AF_INET;
srv.sin_port=25;
s=socket(AF_INET,SOCK_STREAM,0);
if (s==INVALID_SOCKET) {ShowMessage("INVALID_SOCKET");return 0;}
memcpy((char*)&srv.sin_addr,ip_addr->h_addr_list[0],ip_addr->h_length);
if (connect(s,(struct sockaddr*)&srv,sizeof(srv))==-1) {ShowMessage("Can't Connect");return WSAGetLastError();}
Все время получаю сообщение "Can't connect"? Пробовал разные хосты, даже в локалке, все равно не пашет. Помогите плиз.
struct sockaddr_in srv;
struct hostent* ip_addr;
int port,s;
char ip;
char* http_host="ya.ru";
if (WSAStartup(WINSOCK_VERSION, &wsaData)) {ShowMessage("Can't Initialize");return 0;}
ip_addr=gethostbyname(http_host);
if (!ip_addr) {ShowMessage("Can't Resolve Hostname");return 0;}
srv.sin_family=AF_INET;
srv.sin_port=25;
s=socket(AF_INET,SOCK_STREAM,0);
if (s==INVALID_SOCKET) {ShowMessage("INVALID_SOCKET");return 0;}
memcpy((char*)&srv.sin_addr,ip_addr->h_addr_list[0],ip_addr->h_length);
if (connect(s,(struct sockaddr*)&srv,sizeof(srv))==-1) {ShowMessage("Can't Connect");return WSAGetLastError();}
ip_addr=gethostbyname(http_host);
InetAddr = inet_ntoa (*(struct in_addr *)*ip_addr->h_addr_list);
srv.sin_port=htons(25);
srv.sin_addr.s_addr = inet_addr(InetAddr);
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
Ну и настройки сети проверь - может у тебя файрволл не пускает.
так в чем моя ошибка?
неправилно IP передавал в srv?
struct sockaddr_in srv;
struct hostent* ip_addr;
int port,s;
char *InetAddr;
char* http_host="ya.ru";
if (WSAStartup(WINSOCK_VERSION, &wsaData)) {ShowMessage("Can't Initialize");return 1;}
ip_addr=gethostbyname(http_host);
if (!ip_addr) {ShowMessage("Can't Resolve Hostname");return 2;}
InetAddr = inet_ntoa (*(struct in_addr *)*ip_addr->h_addr_list);
memset(&srv, 0, sizeof(srv));
srv.sin_family=AF_INET;
s=socket(AF_INET,SOCK_STREAM,0);
if (s==INVALID_SOCKET) {ShowMessage("INVALID_SOCKET");return 3;}
//memcpy((char*)&srv.sin_addr,ip_addr->h_addr_list[0],ip_addr->h_length);
srv.sin_port=htons(80);
srv.sin_addr.s_addr = inet_addr(InetAddr);
s=socket(AF_INET,SOCK_STREAM,0);
if (s==INVALID_SOCKET) {ShowMessage("INVALID_SOCKET");return 4;}
if (connect(s,(struct sockaddr*)&srv,sizeof(srv))==-1) {ShowMessage("Can't Connect");return 5;}
Edit1->Text="Connected";
char *query=(char*)malloc(2048);
strcpy(query,"GET / HTTP/1.1\r\nHost: ya.ru\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en)\r\nAccept: */*\r\n\r\n");
if (send(s,query,strlen(query),0)==SOCKET_ERROR) return 6;
int size=1024*1024; // 1Mb
char *result=(char*)malloc(size);
AnsiString res;
strcpy(result,"");
int bytesrec=1;
while (true)
{
strcpy(result,"");
bytesrec=recv(s,result,sizeof(size),0);
res+=result;
if (res.Pos("</html>")) break;
}
Теперь возникла друная проблема.
при получении ответа с сервера, не могу закончить цикл после принятия последнего байта.
Делал так:
while (bytesrec!=0)
{
bytesrec=recv(s,result,sizeof(size),0);
...
}
работает но долго, видимо, когда сокет по таймауту отключается.
пробовал искать в полученной строке </html> -работает быстро, но это если точно знаешь что оно там есть.
Хотелось бы так - заканчиваються данные выходить из цикла, желательно побыстрее
while (bytesrec!=0)
{
bytesrec=recv(s,result,sizeof(size),0);
size-=bytesrec;
result[bytesrec]=0;
res+=result;
}
при таком 5-10 сек.
{
bytesrec=recv(s,result,sizeof(size),0);
size-=bytesrec;
result[bytesrec]=0;
res+=result;
if (res.Pos("</html>")) break;
}
while (bytesrec!=0)
{
bytesrec=recv(s,result,sizeof(size),0);
size-=bytesrec;
result[bytesrec]=0;
res+=result;
}
при таком 5-10 сек.
{
bytesrec=recv(s,result,sizeof(size),0);
size-=bytesrec;
result[bytesrec]=0;
res+=result;
if (res.Pos("</html>")) break;
}
но если в принятом тексте нет символов "</html>", то ерунда получаеться
Как же быть, не хочеться ждать лишнее время.