Проблема с сокетом: некоторые отправленные байты становятся неполными при получении - PullRequest
0 голосов
/ 19 февраля 2012

ПОСЛЕДНИЕ ОБНОВЛЕНИЯ (как я решил свою проблему)

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

Что решило мою проблему, отправивСтрока клиенту до получения байтов.

            TcpClient tcpFileSender = (TcpClient)htUsers[FileSender];                
            StreamWriter swWrtr = new StreamWriter(tcpFileSender.GetStream());
            StreamReader srRdr = new StreamReader(tcpFileSender.GetStream());

            //tell the client app that the server is ready for data transfer
            swWrtr.WriteLine("#READY");
            swWrtr.Flush();

            //receive file name and file size
            string filename = srRdr.ReadLine();                
            string filesizeSTR = srRdr.ReadLine();
            Int32 filesize = Convert.ToInt32(filesizeSTR);

            //Socket s = tcpFileSender.Client; //socket
            NetworkStream s = tcpFileSender.GetStream(); //network stream
            //NetworkStream s = tcpFileSender.GetStream();
            //string tmpFile = Path.GetTempFileName();

            //string newfile = path.changeextension(tmpfile, ".zip");
            string desktop = "C:\\Users\\Anonymous\\Desktop\\";
            string tmpFile = desktop + filename;
            //File.Move(tmpFile, newfile);
            //tmpFile = newfile;

            string extension = Path.GetExtension(tmpFile);
            string filenameonly = Path.GetFileNameWithoutExtension(tmpFile);
            int i = 2;
            while( File.Exists(tmpFile) )
            {
                tmpFile = desktop + filenameonly + i.ToString() + extension;
                i++;
            }

            Console.WriteLine("File size: " + filesizeSTR);
            FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
            byte[] buffer = new byte[0x1000];
            int szRead;


            // These two lines of code solved the problem of "missing" bytes
            swWrtr.WriteLine("#BEGIN");
            swWrtr.Flush();

            do
            {
                //int szRead = s.Receive(buffer, buffer.Length, SocketFlags.None); //socket
                szRead = s.Read(buffer, 0, buffer.Length);
                Console.WriteLine(szRead.ToString());
                if (szRead > 0)
                {
                    ms.Write(buffer, 0, szRead);
                }
            }
            while (ms.Length < filesize);

// other codes for saving the file....

У меня есть клиентская программа, которая отправляет файл в серверную программу.

Вот как клиентская программа отправляет файл в серверную программу

while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
{
    destination.Write(buffer, 0, read);
    Console.WriteLine(read.ToString());
}

//read is an int
//source is a FileStream
//buffer is a byte[]
//destination is a NetworkStream

Вот как серверная программа получает файл от клиента

    do
    {
        szRead = s.Receive(buffer, buffer.Length, SocketFlags.None);
        Console.WriteLine(szRead.ToString());
        if (szRead > 0)
        {
            ms.Write(buffer, 0, szRead);
        }
    }
    while (ms.Length < fileSize);

// szRead is an int
// s is a Socket
// buffer is a byte[]
// ms is a FileStream
// fileSize is an int

Вот вывод консоли при запуске моей программы:

(на стороне клиента)

4096 4096 4096 4096 4096 4096 4096 2560

(на стороне сервера)

4096 4096 4096 4096 4096 3079 4096 2560

Поскольку я получаю неполные байты, серверПрограмма не может восстановить файл, отправленный клиентской программой.Как я могу решить эту проблему?

РЕДАКТИРОВАТЬ: Я использую TCP

РЕДАКТИРОВАТЬ:

Клиент: (Извините, я не могу опубликовать полный код. МойПрограмма довольно большая)

public partial class UserLogInForm : Form
{
    private TcpClient tcpServer;
    private IPAddress ipAddr; 
    public string ipaHolder;

    public UserLogInForm()
    {
        InitializeComponent();
        ipaHolder = "192.168.1.55";
    }

    private bool InitializeConnection()
    {
        ipAddr = IPAddress.Parse(ipaHolder);
        tcpServer = new TcpClient();
        tcpServer.Connect(ipAddr, 1986);

        //My application's actually a chat application as well, so I need the following
        //These isn't how my program exactly looks like but these are actual codes from my program
        swSender = new StreamWriter(tcpServer.GetStream());
        swSender.WriteLine(UserName);
        swSender.Flush();

        srReceiver = new StreamReader(tcpServer.GetStream());
        string ConResponse = srReceiver.ReadLine();

        MyMainForm anotherForm = new MyMainForm(UserName, swSender, srReceiver, tcpServer, this)
    }
}

    public partial class MyMainForm : Form
{
private StreamWriter swSender;
private StreamReader srReceiver;
        private TcpClient tcpServer;

public timex(string User, StreamWriter swSenderArg, StreamReader srReceiverArg, TcpClient tcpServerArg, UserLogInForm logInForm)
    {
    InitializeComponent();
    swSender = swSenderArg;
              srReceiver = srReceiverArg;
              tcpServer = tcpServerArg;
    }

private void fileToServer(string filename)
          {
    try
             {
                FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                TcpClient cli = tcpServer;
                NetworkStream ns = cli.GetStream();

                CopyStreamToStream(fs, ns, null);
                ns.Flush();
   }
catch
         {
               MessageBox.Show("An error occurred while uploading the file to the server");
        }

public static void CopyStreamToStream(Stream source, Stream destination, Action<Stream, Stream, Exception> completed)
    {
        byte[] buffer = new byte[0x1000];
        int read;

        Console.WriteLine("File size: " + source.Length);
        try
        {
            while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
            {
                destination.Write(buffer, 0, read);
                Console.WriteLine(read.ToString());
            }
            if (completed != null) completed(source, destination, null);
        }
        catch (Exception exc)
        {
            if (completed != null) completed(source, destination, exc);
        }
    }
    }

Сервер

namespace ChatServerBase
{

class ChatServer
{
    private TcpListener tlsClient;

    private void Listen()
    {
        tcpClient = tlsClient.AcceptTcpClient();
        Connection newConnection = new Connection(tcpClient);
    }

    public static void ReceiveFile()
    {
         // some codes
         Socket s = tcpFileSender.Client;

        //some codes

                 do
    {
        szRead = s.Receive(buffer, buffer.Length, SocketFlags.None);
        Console.WriteLine(szRead.ToString());
        if (szRead > 0)
        {
            ms.Write(buffer, 0, szRead);
        }
    }
    while (ms.Length < fileSize);

    //some codes
     }
}   

  class Connection
 {
       public Connection(TcpClient tcpCon)
    {
        tcpClient = tcpCon;
        thrSender = new Thread(AcceptClient);
        thrSender.Start();
    }

    private void AcceptClient()
    {
          //some codes
       ChatServer.ReceiveFile(currUser);
            //some codes
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...