2015-01-03 5 views
-1

내 파일 공유 응용 프로그램에서 클라이언트 측의 데이터를 수신하는 곳이 부족합니다. FileStream.copyto()을 사용합니다. 현재 잘 작동하지만 현재 버퍼를 설정했습니다 var bytesread = fs.Read(buffer, 0, buffer.Length)하지만 대한 1024의 크기 나는 두 가지 문제가 있습니다데이터를 복사하기 전에 서버 측에서 클라이언트 파일 이름을 얻는 방법

  1. 나는 그것이 히트 및 시험 방법이 될 overflow.Should 버퍼 전에 허용하는 최대 크기에 대한 확실 해요? 또는 WLAN에서 데이터를 전송하기위한 고정 바이트 제한이 있습니다.

  2. 내가 path을 미리 정의한 FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)과 같은 확장명의 하드 코드 된 파일 이름을 사용하여 서버 측에서 코드를 검사했을 때 작동하지만 어떻게 파일 이름을 가져올 수 있습니까? 내 말은, 나는 사전 데이터 바이트를 할당해야하고 수정 후 & 데이터를 복사하기 전에 서버 측에 수신 확인 프로토콜을 사용해야합니까?

좋은 생각.

+0

버퍼 크기는 성능에만 영향을줍니다. 구체적인 위험이 보이십니까? – usr

+1

분명히 파일 이름을 어떻게 든 보내야합니다. 원격 측에서 이름을 알 수있는 다른 방법은 없을까요? 이름을 보내는 데 어떤 구체적인 문제가 있습니까? – usr

+0

방금 ​​파일 이름을 보내려는 아이디어를 물었습니다. –

답변

1

코드가없고보다 정확한 설명이 없으므로 여기서 실제로 필요한 것이 무엇인지 알기가 어렵습니다. 그러나 올바르게 이해하면 클라이언트 엔드 포인트가 로컬 파일을 읽고 서버 엔드 포인트로 데이터를 보내는 시나리오가 있으며 서버 엔드 포인트는 I/O에 NetworkStream 오브젝트를 사용합니다. 당신이 할 수있는, 이미 적절한 크기의 byte[] 버퍼에 데이터를 읽고 가정, 서버에서

void TransmitFileName(Stream stream, string fileName) 
{ 
    byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileName), 
     fileNameLengthBytes = BitConverter.GetBytes(fileNameBytes.Length); 

    stream.Write(fileNameLengthBytes, 0, 4); 
    stream.Write(fileNameBytes, 0, fileNameBytes.Length); 
} 

: 그런 경우 가정

는, 클라이언트는 같은 것을 사용하여 파일 이름을 포함 할 수 있습니다 다음과 같은 정보를 디코딩 :

string DecodeFileName(Stream stream) 
{ 
    byte[] fileNameLengthBuffer = new byte[4]; 

    FillBufferFromStream(stream, fileNameLengthBuffer); 
    int fileNameLength = BitConverter.ToInt32(fileNameLengthBuffer, 0); 

    byte[] fileNameBuffer = new byte[fileNameLength]; 

    FillBufferFromStream(stream, fileNameBuffer); 
    return Encoding.UTF8.GetString(fileNameBuffer); 
} 

void FillBufferFromStream(Stream stream, byte[] buffer) 
{ 
    int cbTotal = 0; 
    while (cbTotal < buffer.Length) 
    { 
     int cbRead = stream.Read(buffer, cbTotal, buffer.Length - cbTotal); 

     if (cbRead == 0) 
     { 
      throw new InvalidDataException("premature end-of-stream"); 
     } 

     cbTotal += cbRead; 
    } 
} 

난 독자 운동으로 실제 서버 측의 I/O를 떠난다. 그러나 TCP를 사용하면 요청한 모든 바이트가 읽혀질 때까지 주어진 읽기 작업이 보장되지 않습니다. 따라서 디코딩 작업을 성공적으로 수행하는 데 필요한 모든 바이트를 얻을 때까지 계속 읽을 필요가 있습니다.

< 편집> 나는 NetworkStream 개체에서 데이터를 읽는 데 필요한 논리를 추가했습니다. 실제로 읽은 바이트 수를 검사하고 필요한 바이트 수가 실제로 읽힐 때까지 버퍼를 채우는 도우미 메서드를 포함합니다. Read() 메서드를 사용하면 원하는 모든 바이트를 실제로 읽을 때까지 차단할 수 없습니다. </EDIT>

실제로, 이것은 아마도 두 부분으로 디코딩하고 의미 : 파일 이름을 얻기 위해 (당신이 4 바이트가 필요 알고)에 fileNameLength 값, 두 번째 부분을 얻기 위해 첫 번째 부분을합니다 (길이는 fileNameLength 값을 디코딩 한 후에 만 ​​알 수 있습니다).

파일 이름의 바이트 다음에 이전과 마찬가지로 파일 데이터를 전송할 수 있습니다.


편집 : 위 코드를 & hellip;

클라이언트 : 실제 파일 데이터를 보내기 전에 TransmitFileName() 메서드를 호출하십시오. 예컨대 :

using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) 
{ 
    TransmitFileName(netstream, Path.GetFileName(path)); 
    ... 

서버 : 호출하면 실제 파일 데이터를 수신하기 전에 DecodeFileName() 방법. 예 :

//open a stream to get data 
NetworkStream netStream = client.GetStream(); 

//Directory to save 
string DirName = @"D:\NewFolder\Test\"; 

//File Name is requirement here to save data at. 

string fileloc = Path.Combine(DirName, DecodeFileName(netStream)); 
MessageBox.Show(fileloc); 
+0

왜'fileNameLengthBytes'에'4 바이트'가 필요합니까? –

+0

배열의 길이는 'System.Int32'유형, 즉 32 비트 정수, 즉 4 바이트로 표시되기 때문에. 더 작아 질 수 있습니다. length가 65535보다 길지 않다면 2 바이트 ('System.Int16' aka'short'), 255보다 길지 않으면 1 바이트 ('System.Byte' aka'byte')가됩니다.하지만'int'는 I/O 코드를 기본 메모리 내 데이터와보다 일관성있게 만드십시오. 스트림의 몇 바이트가 눈에 띄는 차이를 만들지 않을 것입니다. –

+0

질문 코드가 업데이트되었습니다. 내 시나리오를 지금보실 수 있습니다. –