У меня есть клиент и сервер, клиент отправляет файл на сервер. Когда я передаю файлы на моем компьютере (локально), все в порядке (попробуйте отправить файл размером более 700 МБ).
Когда я пытаюсь отправить файл через Интернет моему другу, в конце отправки появляется ошибка на сервере «Входная строка не в правильном формате». Эта ошибка появляется в этом выражении fSize = Convert::ToUInt64(tokenes[0]);
- и я не против, что это появляется. Файл должен быть передан и дождаться другой передачи
PS: извините за слишком много кода, но я хочу найти решение
private: void CreateServer()
{
try{
IPAddress ^ipAddres = IPAddress::Parse(ipAdress);
listener = gcnew System::Net::Sockets::TcpListener(ipAddres, port);
listener->Start();
clientsocket =listener->AcceptSocket();
bool keepalive = true;
array<wchar_t,1> ^split = gcnew array<wchar_t>(1){ '\0' };
array<wchar_t,1> ^split2 = gcnew array<wchar_t>(1){ '|' };
statusBar1->Text = "Connected" ;
//
while (keepalive)
{
array<Byte>^ size1 = gcnew array<Byte>(1024);
clientsocket->Receive(size1);
System::String ^notSplited = System::Text::Encoding::GetEncoding(1251)->GetString(size1);
array<String^> ^ tokenes = notSplited->Split(split2);
System::String ^fileName = tokenes[1]->ToString();
statusBar1->Text = "Receiving file" ;
unsigned long fSize = 0;
//IN THIS EXPRESSIN APPEARS ERROR
fSize = Convert::ToUInt64(tokenes[0]);
if (!Directory::Exists("Received"))
Directory::CreateDirectory("Received");
System::String ^path = "Received\\"+ fileName;
while (File::Exists(path))
{
int dotPos = path->LastIndexOf('.');
if (dotPos == -1)
{
path += "[1]";
}
else
{
path = path->Insert(dotPos, "[1]");
}
}
FileStream ^fs = gcnew FileStream(path, FileMode::CreateNew, FileAccess::Write);
BinaryWriter ^f = gcnew BinaryWriter(fs);
//bytes received
unsigned long processed = 0;
pBarFilesTr->Visible = true;
pBarFilesTr->Minimum = 0;
pBarFilesTr->Maximum = (int)fSize;
// Set the initial value of the ProgressBar.
pBarFilesTr->Value = 0;
pBarFilesTr->Step = 1024;
//loop for receive file
array<Byte>^ buffer = gcnew array<Byte>(1024);
while (processed < fSize)
{
if ((fSize - processed) < 1024)
{
int bytes ;
array<Byte>^ buf = gcnew array<Byte>(1024);
bytes = clientsocket->Receive(buf);
if (bytes != 0)
{
f->Write(buf, 0, bytes);
processed = processed + (unsigned long)bytes;
pBarFilesTr->PerformStep();
}
break;
}
else
{
int bytes = clientsocket->Receive(buffer);
if (bytes != 0)
{
f->Write(buffer, 0, 1024);
processed = processed + 1024;
pBarFilesTr->PerformStep();
}
else break;
}
}
statusBar1->Text = "File was received" ;
array<Byte>^ buf = gcnew array<Byte>(1);
clientsocket->Send(buf,buf->Length,SocketFlags::None);
f->Close();
fs->Close();
SystemSounds::Beep->Play();
}
}catch(System::Net::Sockets::SocketException ^es)
{
MessageBox::Show(es->ToString());
}
catch(System::Exception ^es)
{
MessageBox::Show(es->ToString());
}
}
private: void CreateClient()
{
clientsock = gcnew System::Net::Sockets::TcpClient(ipAdress, port);
ns = clientsock->GetStream();
sr = gcnew StreamReader(ns);
statusBar1->Text = "Connected" ;
}
private:void Send()
{
try{
OpenFileDialog ^openFileDialog1 = gcnew OpenFileDialog();
System::String ^filePath = "";
System::String ^fileName = "";
//file choose dialog
if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
filePath = openFileDialog1->FileName;
fileName = openFileDialog1->SafeFileName;
}
else
{
MessageBox::Show("You must select a file", "Error",
MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
return;
}
statusBar1->Text = "Sending file" ;
NetworkStream ^writerStream = clientsock->GetStream();
System::Runtime::Serialization::Formatters::Binary::BinaryFormatter ^format =
gcnew System::Runtime::Serialization::Formatters::Binary::BinaryFormatter();
array<Byte>^ buffer = gcnew array<Byte>(1024);
FileStream ^fs = gcnew FileStream(filePath, FileMode::Open);
BinaryReader ^br = gcnew BinaryReader(fs);
//file size
unsigned long fSize = (unsigned long)fs->Length;
//transfer file size + name
bFSize = Encoding::GetEncoding(1251)->GetBytes(Convert::ToString(fs->Length+"|"+fileName+"|"));
writerStream->Write(bFSize, 0, bFSize->Length);
//status bar
pBarFilesTr->Visible = true;
pBarFilesTr->Minimum = 0;
pBarFilesTr->Maximum = (int)fSize;
pBarFilesTr->Value = 0; // Set the initial value of the ProgressBar.
pBarFilesTr->Step = 1024;
//bytes transfered
unsigned long processed = 0;
int bytes = 1024;
//loop for transfer
while (processed < fSize)
{
if ((fSize - processed) < 1024)
{
bytes = (int)(fSize - processed);
array<Byte>^ buf = gcnew array<Byte>(bytes);
br->Read(buf, 0, bytes);
writerStream->Write(buf, 0, buf->Length);
pBarFilesTr->PerformStep();
processed = processed + (unsigned long)bytes;
break;
}
else
{
br->Read(buffer, 0, 1024);
writerStream->Write(buffer, 0, buffer->Length);
pBarFilesTr->PerformStep();
processed = processed + 1024;
}
}
array<Byte>^ bufsss = gcnew array<Byte>(100);
writerStream->Read(bufsss,0,bufsss->Length);
statusBar1->Text = "File was sent" ;
btnSend->Enabled = true;
fs->Close();
br->Close();
SystemSounds::Beep->Play();
newThread->Abort();
}
catch(System::Net::Sockets::SocketException ^es)
{
MessageBox::Show(es->ToString());
}
}
ОБНОВЛЕНИЕ: 2Ben Voigt - хорошо, я могу добавить проверку, если clientsocket->Receive(size1);
равно нулю, но почему он начинает получать данные снова, в конце получения.
ОБНОВЛЕНИЕ: После добавления этой проверки проблема остается. И WIN RAR SAY ОТКРЫТИЯ АРХИВА - неожиданный конец файла!
ОБНОВЛЕНИЕ: 2Kevin - http://img153.imageshack.us/img153/3760/erorr.gif
Я думаю, что он продолжает получать некоторые байты от клиента (который остается в потоке), но почему? - существует цикл while (processed < fSize)
ОБНОВЛЕНИЕ: 2Ben Voigt -i сделал это исправление processed += bytes;
и файл успешно передан. Спасибо!
Я не очень хорошо разбираюсь в английском, и я не понимаю, что вы имеете в виду, когда говорите: «Подумайте, что произойдет, если ваше начальное чтение зацепит часть данных файла ...» Что означает зацепки? А какие исходные данные вы имеете в виду?