Przesyłanie obrazu przez TCP klient-serwer (Asynchroniczny serwer)

0

Witam, mam problem z odbiorem danych po stronie klienta. Wykorzystuję asynchroniczny serwer w którym chcę wysyłać obraz.
Oto kod źródłowy serwera:


    public class StateObject
    {
        // Gniazdo klienta.
        public Socket workSocket = null;
        // Rozmiar bufora odbioru.
        public const int BufferSize = 1024;
        // Bufor odbioru.
        public byte[] buffer = new byte[BufferSize];
        // Odebrany ciąg danych.
        public StringBuilder sb = new StringBuilder();
    }

    public class AsynchronousSocketListener : Form1
    {
        public static ManualResetEvent allDone = new ManualResetEvent(false);

        public AsynchronousSocketListener()
        {
        }

        public static void StartListening()
        {

            // Utworzenie lokalnego punktu końcowego dla gniazda.
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, socketIn);

            // Stworzenie gniazda TCP/IP.
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(100);

                while (true)
                {
                    // Ustaw zdarzenie do stanu niesygnalizowanego.
                    allDone.Reset();

                    // Włącz asynchroniczne gniazdo do nasłuchiwania połączeń.
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

                    allDone.WaitOne();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }


        public static void AcceptCallback(IAsyncResult ar)
        {
            allDone.Set();

            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            // Stwórz obiekt stanu.
            StateObject state = new StateObject();
            state.workSocket = handler;

            obraz = makeScreenShot();

            // Konwertuj obraz na dane typu byte
            MemoryStream ms = new MemoryStream();
            obraz.Save(ms, ImageFormat.Jpeg);
            byte[] byteObraz = ms.GetBuffer();
            ms.Close();
                
            // Rozpocznij wysyłanie danych do urządzenia zdalnego.
            handler.BeginSend(byteObraz, 0, byteObraz.Length, 0, new AsyncCallback(SendCallback), handler);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;

                // Zakończ wysyłanie danych do urządzenia zdalnego.
                int bytesSent = handler.EndSend(ar);
                string test = bytesSent.ToString();
                MessageBox.Show("Sent " + test + " bytes to client.",test);


                handler.Shutdown(SocketShutdown.Both);
                handler.Close();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

Niestety po stronie klienta otrzymuję wyjątek dla metody ReadBytes klasy BinaryReader że parametr count musi być nieujemny. Po sprawdzeniu debuggerem wartość ta rzeczywiście jest ujemna. Wnioskuję że dane w ogóle nie dotarły pomimo że po stronie serwera otrzymałem komunikat że:
"Sent " + test + " bytes to client."
Poniżej znajduje się kod klienta:

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync(); 
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            string host = textBox1.Text;
            int port = System.Convert.ToInt16(numericUpDown1.Value);

            try
            {
                TcpClient klient = new TcpClient(host, port);

                NetworkStream ns = klient.GetStream();
                while (klient.Connected)
                {
                    byte[] obrazByte;
                    using (BinaryReader odczytObrazu = new BinaryReader(ns))
                    {
                        int rozmiarObrazu = odczytObrazu.ReadInt32();
                        obrazByte = odczytObrazu.ReadBytes(rozmiarObrazu);
                    }
                    using (MemoryStream ms = new MemoryStream(obrazByte))
                    {
                        Image obraz = Image.FromStream(ms);
                        pictureBox1.Image = obraz;
                    }
                }
                klient.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());

            }
          }
        }
    }

 

Moim zamiarem jest ciągłe wysyłanie obrazu jeden za drugim aby otrzymać przyzwoity framerate (tak wiem że z tym jest temat rzeka, ale na razie nie zagłębiam się skoro nie poradzę wysłać jednego obrazu).

0

Trochę offtop, ale czemu nie napiszesz tego z użyciem async/await(TAP) tylko bawisz się w IAsyncResult?

1 użytkowników online, w tym zalogowanych: 0, gości: 1