我有一个客户端和服务器,客户端将文件发送到服务器。当我在本地计算机上传输文件时,一切正常(尝试将文件传输到700mb以上)。
当我尝试在发送结束时使用Internet向我的 friend 发送文件时,在服务器上出现错误“输入字符串格式不正确”。此错误出现在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表示要打开存档-文件意外结束!
更新:2Kevin-http://img153.imageshack.us/img153/3760/erorr.gif
我认为它继续从客户端接收一些字节(保留在流中),但是为什么呢? -存在周期
while (processed < fSize)
更新:2Ben Voigt -i修复了
processed += bytes;
并成功传输了文件。谢谢!我的英语水平不是很好,并且当我说“考虑如果您的初始读取阻塞了文件数据的一部分会发生什么情况……”时,您的意思是什么?您指的是什么初始数据?
最佳答案
不要忽略clientsocket->Receive(size1)
的返回值。
DOC:“ Socket.Receive
Method ( Byte[]
)”
编辑:考虑如果您的初始读取阻塞了文件数据的一部分会发生什么。还请考虑一下,如果您的上次读取(由于某种原因仍然是1024个字节而不是剩余的字节数)阻塞了下一个请求的 header 的一部分,将会发生什么情况。
编辑:您还没有对Receive
的返回值做任何有用的事情。您的代码行:
processed = processed + 1024;
需要是
processed += bytes;
编辑:“snags”的意思是“捕获”或“抓斗”
你有:
clientsocket->Receive(size1);
再过一会儿:
clientsocket->Receive(buf);
并假设所有 header 数据都在
size1
中,所有文件数据都在buf
中。在流套接字上,这不是一个安全的假设。数据报套接字保留消息边界,而TCP等流套接字则不会。实际上,Nagle的算法甚至可能使文件数据的第一部分与报头放入同一网络数据包中,但是即使不这样做,接收方的TCP堆栈也会丢弃数据包边界,只是将内容放入一个大接收缓冲区。
关于c# - 使用.net套接字的文件,传输问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2669493/