Есть сервер и клиент.. (работают асинхронно)
Сервер посылает клиенту допустим 10кб информации..
Клиент же полчает сначала 1040, а потом ещё дополучает...
Могу привести кода немножко)
сервер:
public void SearchFileOnServer(String Path, String FileMask, UserConnection Sender)
{
Int32 CountOfFounfFiles = 0, CountOfSendBytes = 0;
String AllFounfFiles = "";
Sender.SendData("BEGIN_TO_FIND|");
SetRichTextBoxText("Start Searching for " + FileMask + " in " + Path + " and Subdirectories...\n");
ScrollRichTextBox(-1);
try
{
foreach (String FoundFile in Directory.GetFiles(Path, FileMask, System.IO.SearchOption.TopDirectoryOnly))
{
AllFounfFiles += FoundFile + "|"; // накапливаем строку из найденных файлов
CountOfFounfFiles++; // кол-во найденных фалов
CountOfSendBytes += AllFounfFiles.Length; // кол-во "найденных" БАЙТОВ (имена файлов)if (AllFounfFiles.Length > 10000) // если длина всех найденных файлов больше 948576 б,
// то пошлём клиенту часть и обнулим строку
{
Sender.SendData("FOUNDFILE|" + AllFounfFiles);
AllFounfFiles = "";
}
}
}
catch (DirectoryNotFoundException ex)
{
SetRichTextBoxText("Directory " + Path + " not found!\n");
// ПОСЛАТЬ КЛИЕНТУ ОШИБКУreturn;
}
catch (UnauthorizedAccessException ex) // ВОЗНИКАЕТ, ЕСЛИ НЕТ ДОСТУПА К ПАПКЕ
{
MessageBox.Show(ex.Message);
SetRichTextBoxText("Search error!\n");
// ПОСЛАТЬ КЛИЕНТУ ОШИБКУ Sender.SendData("ERROR|"...);return;
}
try
{
foreach (String dir in SearchFiles.GetAllDirectories(Path))
foreach (String FoundFile in Directory.GetFiles(dir, FileMask, System.IO.SearchOption.TopDirectoryOnly))
{
AllFounfFiles += FoundFile + "|";
CountOfFounfFiles++;
CountOfSendBytes += AllFounfFiles.Length;
if (AllFounfFiles.Length > 10000) // если длина всех найденных файлов больше 80 r,? то пошлём коиенту
{
Sender.SendData("FOUNDFILE|" + AllFounfFiles);
AllFounfFiles = "";
}
}
}
catch (UnauthorizedAccessException ex) // ВОЗНИКАЕТ, ЕСЛИ НЕТ ДОСТУПА К ПАПКЕ
{
//MessageBox.Show(ex.Message);
SetRichTextBoxText("Search error!\n");
// ПОСЛАТЬ КЛИЕНТУ ОШИБКУ Sender.SendData("ERROR|"...);return;
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
SetRichTextBoxText("Search error!\n");
// ПОСЛАТЬ КЛИЕНТУ ОШИБКУ Sender.SendData("ERROR|"...);return;
}
SetRichTextBoxText("Search complete! Found " + CountOfFounfFiles.ToString() +
" files. Send to client " + CountOfSendBytes + " bytes.\n");
Sender.SendData("FOUNDFILE|" + AllFounfFiles);
}
public void SendData(String Data)
{
// закрываем поток от других. чтобы быть уверенными, что нам никто не помешает =)lock (Client.GetStream())
{
StreamWriter wrt = new StreamWriter(Client.GetStream());
wrt.Write(Data + (char)13 + (char)10);
// чтобы все данные записались
wrt.Flush();
}
}
Клиент:
private void DoRead(IAsyncResult ar)
{
Int32 BytesRead;
String strMessage;
try
{
// Заканчивает чтение данных в readBuffer и возвращает кол-во прочитанных байт
// lock (Client.GetStream())
{
BytesRead = Client.GetStream().EndRead(ar);
}
if (BytesRead < 1)
{
// TO_DO!!! если ничего не было прочитано то server закрыт. Отметить, что разъединено в catch
// MarkAsDisconnected();return;
}
// конвертируем в кодировку UTF8 и отнимаем 2 байта: Chr(13) и Chr(10)
strMessage = Encoding.UTF8.GetString(readBuffer, 0, BytesRead - 2);
// анализируем команды
ProcessCommands(strMessage);
// заново начинаем чтение
Client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
}
catch (IOException ex)
{
MessageBox.Show("Сервер разорвал сеодинение. Возможно он завершил работу. Попробуйте подключиться позже.",
"LocalNetSearchClient Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
MenuStripChangeDisconnect(Color.Red, "Нет соединения с сервером", true);
}
catch (Exception e)
{
//MessageBox.Show(e.Message);
//отсоединитьсяToolStripMenuItem_Click(null, null);
}
}
наверняка я неправильно что-то делаю... но что?
Не могу понять, как правильно передавать по сети..
От:
Аноним
Дата:
27.10.06 07:14
Оценка:
Что это READ_BUFFER_SIZE?
И что Вас удивляет?
BytesRead = Client.GetStream().EndRead(ar);
а затем
Client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
Здравствуйте, masterklass, Вы писали:
M>READ_BUFFER_SIZE — размер массива, куда считываем...
M>хм... M>я брал за основу пример MS из 101 примера для .net.. M>там так.. саам немного удивился поначалу.. M>как же тогда написать?
M>данное сообщение получено с www.gotdotnet.ru M>ссылка на оригинальное сообщение
Re[2]: Не могу понять, как правильно передавать по сети..
Кстати я это и делаю..
Как только к серверу подключаюсь..
try
{
if (toolStripTextBox1.Text == "" || toolStripTextBox2.Text == "")
{
MessageBox.Show("Введите IP и Port сервера!");
return;
}
Client = new TcpClient(ServerIP, PORT_NUM);
// запускаем отдельный поток на получение данных от клиента (чтоб не грузить форму)
Client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
}
catch (Exception ex)
{
MessageBox.Show("Ошибка при подключении к серверу! Возможно он не запушен или Вы неверно ввели IP или порт сервера!",
"LocalNetSearchClient Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
//this.Dispose();
}
Здравствуйте, MasterKlass, Вы писали:
MK>Надо сначала Beginread() где-нить указать?
MK>Здравствуйте, masterklass, Вы писали:
M>>READ_BUFFER_SIZE — размер массива, куда считываем...
M>>хм... M>>я брал за основу пример MS из 101 примера для .net.. M>>там так.. саам немного удивился поначалу.. M>>как же тогда написать?
M>>данное сообщение получено с www.gotdotnet.ru M>>ссылка на оригинальное сообщение
Re[2]: Не могу понять, как правильно передавать по сети..
От:
Аноним
Дата:
30.10.06 18:11
Оценка:
ну так а всё же...
почему клмент принмает не полностью строку, что я ему посылаю?
в чём может быть проблема?
Здравствуйте, masterklass, Вы писали:
M>ну так а всё же...
M>почему клмент принмает не полностью строку, что я ему посылаю? M>в чём может быть проблема?
Это не проблема, это архитектура сети. Данные разбиваются на пакеты и отправляются пакетами и приходят... точно, тоже пакетами!
Re[4]: Не могу понять, как правильно передавать по сети..
Здравствуйте, Andrbig, Вы писали:
A>Здравствуйте, masterklass, Вы писали:
M>>ну так а всё же...
M>>почему клмент принмает не полностью строку, что я ему посылаю? M>>в чём может быть проблема?
A>Это не проблема, это архитектура сети. Данные разбиваются на пакеты и отправляются пакетами и приходят... точно, тоже пакетами!
"Глупая" архитектура! =)
Надо свою сделать)
Но вроде пока всё норм...
Re[4]: Не могу понять, как правильно передавать по сети..
От:
Аноним
Дата:
01.11.06 11:13
Оценка:
нет. не нормально.
попробую объяснить проблему.
Теоретически:
клиент шлёт запрос на поиск допусти всех файлов *.txt на сервере.
Сервер начинает поиск. Нашёл первый файл и отправил его клиенту.
Клиент получает и добавляет имя и путь файла в listbox.
Практически:
С Сервером всё нормально. Посылает по одному файлу за раз.
А вот с Клиентом...
Вот код процедуры, которая принимает соообщения:
try
{
// Заканчивает чтение данных в readBuffer и возвращает кол-во прочитанных байтlock (Client.GetStream())
{
BytesRead = Client.GetStream().EndRead(ar);
}
if (BytesRead < 1)
{
// TO_DO!!! если ничего не было прочитано то server закрыт. Отметить, что разъединено в catch
// MarkAsDisconnected();return;
}
// конвертируем в кодировку UTF8 и отнимаем 2 байта: Chr(13) и Chr(10)
strMessage = Encoding.UTF8.GetString(readBuffer, 0, BytesRead - 2);
//fl.WriteLine(strMessage);
// анализируем команды
ProcessCommands(strMessage);
// заново начинаем чтение
Client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
}
Первый раз всё нормально, в strMessage содержиться ровно одно имя и путь файла (структура такова — "FOUNDFILE|путь и имя файл|"). А вот потом в strMessage начинают накапливаться имена и пути файлов, т.е. типа такого "FOUNDFILE|файл1|FOUNDFILE|файл2|FOUNDFILE|файл3|FOUNDFILE|файл4|FOUNDFILE|файл5|FOUNDFILE|файл6|FOUNDFILE|файл7|"
и всё бы ничего, но это последовательность в строке может прерваться в самый неподходящий момент, например на середине файла или команды...
Так вот как избежать такого?
Как мне быть уверенным, что приметься только "FOUNDFILE|путь и имя файл|" и всё.
Как сделать, чтобы не накапливалась строка?
Делать огромный буфер на приём (да и то не факт...)?