2010-04-19 6 views
1

클라이언트와 서버 클라이언트가 서버에 파일을 보내고 있습니다. 내 컴퓨터에서 파일을 전송할 때 (로컬) 모든 것이 괜찮습니다 (700MB 이상의 파일을 보내려고 시도하십시오)..net 소켓을 사용하여 파일을 전송하는 중, 문제가 발생했습니다.

보낼 때 내 친구에게 인터넷으로 파일 보내기를 시도하면 "입력 문자열이 올바른 형식이 아닙니다."라는 오류 메시지가 서버에 표시됩니다.이 오류 메시지는 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()); 
} 
    } 

UPDATE 찾으려면 : 2Ben 보이트를 - 좋아, 내가 clientsocket->Receive(size1); 경우 동일한 제로를 확인 추가 할 수 있지만, 왜 그가받는 데이터의 끝에서 데이터를 다시 받기 시작합니다.

업데이트 : 추가 후이 문제는 계속 발생합니다. 그리고 열어 라 RAR SAVING OF ARCHIVE - 예상치 못한 파일 끝!

업데이트 : 2Kevin - http://img153.imageshack.us/img153/3760/erorr.gif 클라이언트 (스트림에 남아 있음)에서 일부 바이트를 계속 수신한다고 생각하지만 왜 그런가요? - 존재주기 while (processed < fSize)

업데이트 : 2Ben Voigt -i는이 수정본 processed += bytes;을 성공적으로 전송했습니다. 감사합니다. 영어로 잘하지 않아서 "처음 읽는 것이 파일 데이터의 일부를 방해한다면 어떻게 될지 생각해보십시오"라고 말하는 것이 무슨 뜻인지 이해하지 못합니다. " 그리고 어떤 초기 데이터를 의미합니까?

+1

"notSplited"및 tokenes [0] 및 tokenes [1]의 값을 인쇄합니다.그것은 많이 보여줄 것입니다. 어떻게해야하는지 다른 문제가 있다고 생각하지만, 적어도 특정 문제를 진단하기위한 시작일 것입니다. –

답변

3

clientsocket->Receive(size1)의 반환 값을 무시하지 마십시오.

DOC : "Socket.Receive Method (Byte[])"

편집 : 초기 읽기는 파일 데이터의 일부를 방해한다 발생했을 때 어떤 일이 일어나는지 보자. 또한 마지막 읽기 (어떤 이유로 든 나머지 바이트 수 대신 1024 바이트)가 다음 요청의 헤더 부분을 방해하는 경우 어떻게되는지 고려하십시오.

편집 : Receive의 반환 값과 관련된 유용한 정보도 아직 준비하지 않았습니다. 코드의 귀하의 라인 :

processed = processed + 1024; 

필요

processed += bytes; 

편집 될 :

clientsocket->Receive(size1); 

및 "그루터기"는 "캡처"또는 "잡고"당신은이

을 의미한다 잠시 후 :

clientsocket->Receive(buf); 

이고 모든 헤더 데이터가 size1이고 모든 파일 데이터가 buf 인 것으로 가정합니다. 스트림 소켓에서는 안전한 가정이 아닙니다. 데이터 그램 소켓은 메시지 경계를 보존하고 TCP와 같은 스트림 소켓은 유지하지 않습니다. 사실, Nagle의 알고리즘은 심지어 파일 데이터의 첫 번째 부분을 헤더와 동일한 네트워크 패킷에 넣을 수도 있지만 그렇지 않은 경우에도 수신자의 TCP 스택은 패킷 경계를 버리고 단지 물건을 하나에 넣습니다 큰 수신 버퍼.

관련 문제