[장착] C# 고성능 대용량 SOCKET 동시 제공(9): 중단 시간 연장

인터럽트 리셋 업로드
단점 리셋은 주로 파일을 업로드하거나 다운로드하는 데 사용되는데 일반적인 방법은 업로드를 시작할 때 서버가 지난번에 업로드한 크기를 되돌려주고 업로드가 완료되면 -1로 되돌려줍니다.다운로드가 시작되었을 때 클라이언트가 로컬에 다운로드 크기를 보고하고 서버가 위치 정보에 따라 데이터를 보내기 때문에 다운로드 프로토콜을 업로드하려면 크기가 필요합니다. 예를 들어 저희 프로토콜 형식입니다.
업로드 시작:
클라이언트-> 서버
{
[Request]
Command=Upload
Dir=Dir # 디렉토리, 전체 경로 이름
FileName=FileName # 파일 이름(경로 제외)
}
서버 -> 클라이언트
{
[Response]
Command=Upload
Code=Error Code#오류 코드
Message=Message#오류가 발생하면 오류 설명 정보를 되돌려줍니다.
FileSize=FileSize#업로드된 파일의 크기(재전송용)
}
따라서 클라이언트의 업로드 요청을 받을 때 다음 서버가 마지막으로 받은 파일 주소를 보내야 합니다.
        public bool DoUpload()
        {
            string dirName = "";
            string fileName = "";
            if (m_incomingDataParser.GetValue(ProtocolKey.DirName, ref dirName) & m_incomingDataParser.GetValue(ProtocolKey.FileName, ref fileName))
            {
                if (dirName == "")
                    dirName = Program.FileDirectory;
                else
                    dirName = Path.Combine(Program.FileDirectory, dirName);
                fileName = Path.Combine(dirName, fileName);
                Program.Logger.Info("Start upload file: " + fileName);
                if (m_fileStream != null) // 
                {
                    m_fileStream.Close();
                    m_fileStream = null;
                    m_fileName = "";
                }
                if (File.Exists(fileName))
                {
                    if (!CheckFileInUse(fileName)) // 
                    {
                        m_fileName = fileName;
                        m_fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
                        m_fileStream.Position = m_fileStream.Length; // 
                        m_outgoingDataAssembler.AddSuccess();
                        m_outgoingDataAssembler.AddValue(ProtocolKey.FileSize, m_fileStream.Length);
                    }
                    else
                    {
                        m_outgoingDataAssembler.AddFailure(ProtocolCode.FileIsInUse, "");
                        Program.Logger.Error("Start upload file error, file is in use: " + fileName);
                    }
                }
                else
                {
                    m_fileName = fileName;
                    m_fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    m_fileStream.Position = m_fileStream.Length; // 
                    m_outgoingDataAssembler.AddSuccess();
                    m_outgoingDataAssembler.AddValue(ProtocolKey.FileSize, m_fileStream.Length);
                }
            }
            else
                m_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
            return DoSendResult();
        }

인터럽트 패스 다운로드
다운로드 시작:
클라이언트-> 서버
{
[Request]
Command=Download
Dir=Dir # 디렉토리, 전체 경로 이름
FileName=FileName # 파일 이름(경로 제외)
FileSize=FileSize#클라이언트 로컬 파일 크기, 인터럽트 리셋용
PacketSize=PacketSize#하부 패킷 크기(KB), 속도 테스트용
}
서버 -> 클라이언트
{
[Response]
Command= Download
Code=Error Code#오류 코드
Message=Message#오류가 발생하면 오류 설명 정보를 되돌려줍니다.
}
        public bool DoDownload()
        {
            string dirName = "";
            string fileName = "";
            Int64 fileSize = 0;
            int packetSize = 0;
            if (m_incomingDataParser.GetValue(ProtocolKey.DirName, ref dirName) & m_incomingDataParser.GetValue(ProtocolKey.FileName, ref fileName)
                & m_incomingDataParser.GetValue(ProtocolKey.FileSize, ref fileSize) & m_incomingDataParser.GetValue(ProtocolKey.PacketSize, ref packetSize))
            {
                if (dirName == "")
                    dirName = Program.FileDirectory;
                else
                    dirName = Path.Combine(Program.FileDirectory, dirName);
                fileName = Path.Combine(dirName, fileName);
                Program.Logger.Info("Start download file: " + fileName);
                if (m_fileStream != null) // 
                {
                    m_fileStream.Close();
                    m_fileStream = null;
                    m_fileName = "";
                    m_sendFile = false;
                }
                if (File.Exists(fileName))
                {
                    if (!CheckFileInUse(fileName)) // 
                    {
                        m_fileName = fileName;
                        m_fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
                        m_fileStream.Position = fileSize; // 
                        m_outgoingDataAssembler.AddSuccess();
                        m_sendFile = true;
                        m_packetSize = packetSize;
                    }
                    else
                    {
                        m_outgoingDataAssembler.AddFailure(ProtocolCode.FileIsInUse, "");
                        Program.Logger.Error("Start download file error, file is in use: " + fileName);
                    }
                }
                else
                {
                    m_outgoingDataAssembler.AddFailure(ProtocolCode.FileNotExist, "");
                }
            }
            else
                m_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
            return DoSendResult();
        }

다중 스레드 동시 다운로드
단점 리셋의 한 응용 프로그램은 바로 병행 다운로드이다. 방법은 클라이언트가 여러 개의 라인을 병행하여 같은 파일을 요청하고 각 라인 아래 파일의 일부분을 모두 다운로드한 후에 모든 데이터 블록을 하나의 파일로 통합시키는 것이다.이 서버와 클라이언트 프로토콜은 수정할 필요가 없고 다운로드 논리의 변경만 해야 한다.
다중 스레드 동시 업로드
이것은 이 논리를 지원하기 위해 통신을 정의해야 한다. 주로 서버가 여러 개의 데이터 파일을 하나의 파일로 통합하는 프로토콜 논리를 제공해야 한다.
DEMO 다운로드 주소:http://download.csdn.net/detail/sqldebug_fan/7467745면책 선언: 이 코드는 C#의 포트 프로그래밍 완료를 보여주기 위한 것일 뿐 학습과 연구에만 사용되며 상업용으로는 사용되지 않습니다.수준이 제한되어 있고 C#도 초학에 속하기 때문에 오류는 불가피하다. 지정과 지도를 환영합니다.메일 주소: [email protected].

좋은 웹페이지 즐겨찾기