Question

I'm really having trouble with this. I'm trying to build a server that will connect multiple clients (Keep the connection open) and when it receives an serialized object, it will send that object back out to all connected clients. So far I've been able to send object to the server and deserialize them server side, but I haven't been able to send that object back out to all clients. Here's what I've got so far:

Server code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Multi_Threaded_TCP
{
    class TcpServer
    {
        private TcpListener _server;
        private Boolean _isRunning;

        private List<TcpClient> connectedClients = new List<TcpClient>();

        public TcpServer(int port)
        {
            _server = new TcpListener(IPAddress.Any, port);
            _server.Start();
            Console.Write("Server running...");
            _isRunning = true;
            LoopClients();
        }

        public void LoopClients()
        {
            while (_isRunning)
            {
                // wait for client connection
                //Add the client to the connected clients list
                TcpClient newClient = _server.AcceptTcpClient();
                connectedClients.Add(newClient);
                // client found.
                // create a thread to handle communication
                Thread t = new Thread(new ParameterizedThreadStart(HandleClient));
                t.Start(newClient);
            }
        }

        public void HandleClient(object obj)
        {
            // retrieve client from parameter passed to thread
            TcpClient client = (TcpClient)obj;
            // sets two streams
            StreamWriter sWriter = new StreamWriter(client.GetStream(), Encoding.ASCII);
            StreamReader sReader = new StreamReader(client.GetStream(), Encoding.ASCII);
            // you could use the NetworkStream to read and write, 
            // but there is no forcing flush, even when requested
            Boolean bClientConnected = true;
            while (bClientConnected)
            {
                    //Deserialize into Person object
                try
                {
                    Person p = null;
                    if (!client.Connected)
                        return;
                    NetworkStream strm = client.GetStream();
                    IFormatter formatter = new BinaryFormatter();
                    p = (Person)formatter.Deserialize(strm); // you have to cast the deserialized object
                    strm.Close();
                    Console.WriteLine("Person's first name: " + p.FirstName);
                    //Send the object back out to all connected clients
                    foreach (TcpClient t in connectedClients)
                    {
                        try
                        {
                                TcpClient tt = t;
                                //tt = new TcpClient();
                                //tt.Connect(ipAddress1, portNum1);
                                IFormatter formatter1 = new BinaryFormatter(); // the formatter that will serialize my object on my stream
                                NetworkStream strm1 = tt.GetStream(); // the stream
                                formatter1.Serialize(strm1, p); // the serialization process
                                strm1.Close();
                        }
                        catch
                        {
                        }
                    }
                }
                catch { }
               }

                }
            }
        }

Client code:

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; 

namespace Client
{
    class ClientDemo
    {
        private TcpClient _client;
        private Boolean _isConnected;
        private string ipAddress1;
        private int portNum1;

        public ClientDemo(String ipAddress, int portNum)
        {
            ipAddress1 = ipAddress;
            portNum1 = portNum;
            _client = new TcpClient();
            _client.Connect(ipAddress, portNum);
            Thread HandleCom = new Thread(HandleCommunication);
            HandleCom.Start();
        }

        public void HandleCommunication()
        {
            connectedClients.Add(_client);
            _isConnected = true;
            Person p = null;
            while (_isConnected)
            {
                try
                {
                    //if (_client.GetStream().DataAvailable == false)
                        //return;
                    //System.Windows.Forms.MessageBox.Show("Data available!");
                    //Need to check if theres any data in the object
                    //System.Windows.Forms.MessageBox.Show(_client.GetStream().DataAvailable.ToString());
                    //System.Windows.Forms.MessageBox.Show("");
                    NetworkStream strm = _client.GetStream();
                    IFormatter formatter = new BinaryFormatter();
                    p = (Person)formatter.Deserialize(strm); // you have to cast the deserialized object
                    //strm.Close();
                    if (p != null)
                        System.Windows.Forms.MessageBox.Show(p.FirstName);
                }
                catch
                {
                    //System.Windows.Forms.MessageBox.Show(ex.Message);
                }
            }
        }

        public void SendData(Person data)
        {
            if (!_client.Connected)
            {
                _client = new TcpClient();
                _client.Connect(ipAddress1, portNum1);
            }
            IFormatter formatter = new BinaryFormatter(); // the formatter that will serialize my object on my stream
            NetworkStream strm = _client.GetStream(); // the stream
            formatter.Serialize(strm, data); // the serialization process
            strm.Close();
        }
    }
}

If someone could help me figure this out I'd be really grateful.

Was it helpful?

Solution

Your problem is that you disconnect the socket (by calling NetworkStream.Close) after you read the data on the server making it impossible to broadcast (send) the person object.

Remove the calls to NetworkStream.Close in both the client and the server and your code will work as expected.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top