C # tcp сокет клиент-сервер проблема передачи нескольких файлов - PullRequest
0 голосов
/ 08 декабря 2010

У меня есть 2 приложения, одно из которых является серверным, а другое - клиентским.оба находятся на одном компьютере. У клиента есть одна кнопка.Когда эта кнопка нажата, клиент начинает скачивать файлы с сервера.Проблема в том, что иногда клиентская сторона получала все файлы успешно, но иногда клиентская сторона получала только 1-й файл, а затем прекращала передачу.Что-то не так с кодом ниже?Может ли кто-нибудь показать мне, где я не прав?Я просто новичок в кодировании, как это.помощь очень ценится.Заранее спасибо.Вот код:

Когда пользователь нажимает кнопку на клиенте, клиент отправляет запрос на загрузку файлов с сервера:

//client side
sendRequest("requestFiles ");

Сервер подготовит файлы для загрузки клиентом после получения токена requestFiles.

// server side
if (execmd == "requestFiles")
{
    string[] fList = Directory.GetFiles(folderDir);
    for (int i = 0; i < fList.Length; i++)
    {
        FileInfo fi = new FileInfo(fList[i]);
        string[] mDesc = new string[3];
        mDesc[0] = fi.Name;
        mDesc[1] = fi.Length.ToString();
        mDesc[2] = fi.FullName;
        string fileSend = "CommitRequest " + fi.Name + " " + fi.Length.ToString() + " " + usID + " " + mName;
        sendRequest(fileSend);
        ClientDownloadingFromServer(mDesc[2], mDesc[1], sock);
    }
    sendComment("AllUpDone");
    continue;
}

Для каждого файла, который необходимо загрузить, сервер отправит токен CommitRequest с подробной информацией о файле (имя, размер) Когда клиент получает CommitRequest:

//client side
if (execmd == "CommitRequest")
{
    //get file name and file size
    downloadFileFromServer(sock);
    continue;
}

Метод downloadFileFromServer на клиент:

//client side
private void downloadMapFromServer(Socket s)
{        
    Socket sock = s;
    //prepare directory rootDir to store file
    System.IO.FileStream fout = new System.IO.FileStream(rootDir + "\\" + fileN, FileMode.Create, FileAccess.Write);
    NetworkStream nfs = new NetworkStream(sock);
    long size = int.Parse(fileS);
    long rby = 0;
    try
    {
        //loop till the Full bytes have been read
        while (rby < size)
        {
            byte[] buffer = new byte[1024];
            //Read from the Network Stream
            int i = nfs.Read(buffer, 0, buffer.Length);
            fout.Write(buffer, 0, (int)i);
            rby = rby + i;
        }
        fout.Close();
    }
    catch (Exception ed)
    {
        Console.WriteLine("A Exception occured in file transfer" + ed.ToString());
        MessageBox.Show(ed.Message);
    }
}

Метод clientDownloadFromServer на стороне сервера:

//server side
void ClientDownloadingFromServer(string fiPath, string fiSize, Socket s)
{
    string parm1 = fiPath;
    string parm2 = fiSize;
    try
    {
        FileInfo ftemp = new FileInfo(parm1);
        long total=ftemp.Length;
        long rdby=0 ;
        int len=0 ;
        byte[] buffed = new byte[1024] ;
        // Open the file requested for download 
        System.IO.FileStream fin = new System.IO.FileStream(parm1,FileMode.Open , FileAccess.Read) ;

        NetworkStream nfs = new NetworkStream(sock) ;

        while(rdby < total && nfs.CanWrite)
        {
             //Read from the File (len contains the number of bytes read)
             len =fin.Read(buffed,0,buffed.Length) ;
             //Write the Bytes on the Socket
             nfs.Write(buffed, 0,len);
             //Increase the bytes Read counter
             rdby=rdby+len ;    
        }
        fin.Close();
    }
}

1 Ответ

0 голосов
/ 08 декабря 2010

Проблема связана с обработкой принимаемых байтов как байтов файла или байтов токена. Ваш клиентский код пытается прочитать байты, которые равны размеру буфера. Сервер отправляет токен «CommitRequest» и байты файла один за другим. Итак, допустим, первый размер файла составляет 1200 байтов. Сервер отправит эти 1200 байтов, за которыми следует «CommitRequest» для второго файла, за которым следуют вторые байты файла. Теперь клиент прочитал бы 1024 байта первого файла. И тогда он будет читать следующие 1024 байта - но эти байты будут содержать оставшиеся 176 байтов первого файла, ответ «CommitRequest» от сервера и затем первые несколько байтов второго файла. Ваш клиентский код занимает только первые 176 байтов и игнорирует следующие байты, которые будут содержать данные для следующего файла.

Вы можете решить эту проблему двумя способами - либо убедившись, что оставшиеся байты будут обработаны (это может быть непросто, поскольку оставшиеся байты могут иметь ответ «CommitRequest» частично), либо реструктурируйте свое решение так, чтобы каждая передача файла Инициироваться только после запроса клиента.

...