none
System.Net.Sockets problem : New form is hanging inside my simple chat application! RRS feed

  • Question

  • Hi

    I have a simple chat application which connect client(s) together via my simple server application which transfer chat data between clients according to sender/receiver.

    here is my code in client side to send/receive data to/from server :

    public void SendData(string message)
            {
                NetworkStream clientStream = this._tcpClient.GetStream();
    
                UTF8Encoding encoder = new UTF8Encoding();
                byte[] buffer = encoder.GetBytes(message);
    
                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();
            }


    For receive data :

    public void Connect()
            {
                this._tcpClient.Connect(this._serverEndpoint);            
                this.SetupRecieveCallback();
            }
    
    public void SetupRecieveCallback()
            {
                try
                {
                    AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
                    this._tcpClient.Client.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, this._tcpClient.Client);
                }
                catch (Exception ex)
                {
                    //throw ex;
                }
            }
    
    public void OnRecievedData(IAsyncResult ar)
            {
                // Socket was the passed in object
                Socket sock = (Socket)ar.AsyncState;
                if (!sock.Connected)
                    return;
    
                // Check if we got any data
                try
                {
                    int nBytesRec = sock.EndReceive(ar);
                    if (nBytesRec > 0)
                    {
                        string strRecievedData = Encoding.UTF8.GetString(m_byBuff, 0, nBytesRec);
                        if (!Common.IsSystemMessage(strRecievedData) && this.ServerMessageReceived != null)
                        {
                            this.ServerMessageReceived(this, new ServerMessageEventArgs(strRecievedData));
                        }                                        
    
                        // If the connection is still usable restablish the callback
                        this.SetupRecieveCallback();
                    }
                    else
                    {                    
                        sock.Shutdown(SocketShutdown.Both);
                        sock.Close();
                    }
                }
                catch (Exception ex)
                {
                    //throw ex;
                }
            }

    This code works correct between client/server applications and also another chat client application (if i don't create new form), but when a message arrived from sender chat, i want to show new chat session form to start, but i don't know when show chat form, it will be hang on! can anybody help me what's the problem and how to solve it ?

    Thanks in advance


    http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx


    • Edited by Hamed_1983 Tuesday, September 10, 2019 11:17 PM
    • Moved by CoolDadTx Wednesday, September 11, 2019 1:36 PM Winforms related
    Tuesday, September 10, 2019 11:02 PM

Answers

  • Hi Hamed_1983,

    You need to change another line in FrmDemoClient.cs.

    this.OpenOrUpdateChatSession(e.CmdResult.Command.FromConnectionID, e.CmdResult.Result.ToString());

    change to -

    this.Invoke(new Action(() => { 
        this.OpenOrUpdateChatSession(e.CmdResult.Command.FromConnectionID, e.CmdResult.Result.ToString());
    }));

    Hope it will work. May not be a best solution; but it should work for you.


    Avik Das

    • Marked as answer by Hamed_1983 Thursday, September 12, 2019 8:54 PM
    Thursday, September 12, 2019 7:52 PM

All replies

  • Hi Hamed_1983,

    Thank you for posting here.

    According to your description, you seem to be wondering how to create a new chat session form when a new client connects to the server, because you only give a part of the code, so I did not use your code, but created a new project, you can refer to my code and improve yours.

    Code for Client:

             public partial class ClientForm : Form
        {
            public ClientForm()
            {
                InitializeComponent();
                TextBox.CheckForIllegalCrossThreadCalls = false;
            }
            Socket socketClient = null;
            Thread threadClient = null;
    
            private void BtnServerConn_Click(object sender, EventArgs e)
            {
                socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ipaddress = IPAddress.Parse("IP");
                IPEndPoint endpoint = new IPEndPoint(ipaddress,Port);
                socketClient.Connect(endpoint);
                threadClient = new Thread(RecMsg);
                threadClient.IsBackground = true;
                threadClient.Start();
                connMsg.AppendText("Connect to server success...");
            }
    
            private void RecMsg()
            {
                while (true)
                {
                    byte[] arrRecMsg = new byte[1024 * 1024];
                    int length = socketClient.Receive(arrRecMsg);
                    string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                    //when receive a message 
                    Application.Run(new ClientChatForm(socketClient,strRecMsg));
                }
              
            }
    

    Code for the new form in client when receive a message:

    public partial class ClientChatForm : Form
        {
            Socket socketClient = null;
            Thread threadClient = null;
            public ClientChatForm(Socket socketClient,String firstMsg)
            {
                this.socketClient = socketClient;
                InitializeComponent();
                threadClient = new Thread(RecMsg);
                threadClient.IsBackground = true;
                threadClient.Start();
                txtMsg.AppendText("Server:" + "\r\n" + firstMsg + "\r\n");
            }
            private void RecMsg()
            {
                while (true)
                {
                    byte[] arrRecMsg = new byte[1024 * 1024];
                    int length = socketClient.Receive(arrRecMsg);
                    string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                    txtMsg.AppendText("Server:" + "\r\n" + strRecMsg + "\r\n");
                }
            }
    
            private void ClientSendMsg(string sendMsg)
            {
                byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                socketClient.Send(arrClientSendMsg);
                txtMsg.AppendText("Client:" + "\r\n" + sendMsg + "\r\n");
    
            }
    
            private void BtnSendMsg_Click(object sender, EventArgs e)
            {
                ClientSendMsg(txtSendMsg.Text.Trim());
            }
    
            private void txtCMsg_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Enter)
                {
                    ClientSendMsg(txtSendMsg.Text.Trim());
                }
            }
    
        }
    

    Code for Server:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                
                TextBox.CheckForIllegalCrossThreadCalls = false;
            }
    
            Thread threadWatch = null;
            Socket socketWatch = null; 
    
            private void BtnServerConn_Click_1(object sender, EventArgs e)
            {
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ipaddress = IPAddress.Parse("IP"); 
                IPEndPoint endpoint = new IPEndPoint(ipaddress, Port); 
                socketWatch.Bind(endpoint);
                socketWatch.Listen(20);
                threadWatch = new Thread(WatchConnecting);
                threadWatch.IsBackground = true;
                threadWatch.Start();
                connMsg.AppendText("Start work..." + "\r\n");
            }
    
            Socket socConnection = null;
      
            private void WatchConnecting()
            {
                while (true)
                {
                    socConnection = socketWatch.Accept();
                    connMsg.AppendText("Connect success..." + "\r\n");
                    //Create  a new Form at here
                    Application.Run(new Form2(socConnection,socketWatch));
                }
            }
    }
    


    Code for the new Form:

               public partial class Form2 : Form
        {
    
            Socket socketWatch = null; 
            Thread threadWatch = null;
            Socket sonnection = null;
            public Form2(Socket socConnection,Socket socket)
            {
                sonnection = socConnection;
                socketWatch = socket;
                InitializeComponent();
                socketWatch.Listen(20);
                threadWatch = new Thread(WatchConnecting);
                threadWatch.IsBackground = true;
                threadWatch.Start();
            }
            private void ServerSendMsg(string sendMsg)
            {
                byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                sonnection.Send(arrSendMsg);
                txtMsg.AppendText("Server:" + "\r\n" + sendMsg + "\r\n");
            }
            private void WatchConnecting()
            {
                while (true) 
                {
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg);
                    Thread thr = new Thread(pts);
                    thr.IsBackground = true;
                    thr.Start(sonnection);
                    break;
                }
            }
           
            private void ServerRecMsg(object socketClientPara)
            {
                Socket socketServer = socketClientPara as Socket;
                while (true)
                {
                    byte[] arrServerRecMsg = new byte[1024 * 1024];
                    int length = socketServer.Receive(arrServerRecMsg);
                    string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
                    txtMsg.AppendText("Client:" + "\r\n" + strSRecMsg + "\r\n");
                }
            }
            private void BtnSendMsg_Click_1(object sender, EventArgs e)
            {
                ServerSendMsg(txtSendMsg.Text.Trim());
            }
            private void txtSendMsg_KeyDown(object sender, KeyEventArgs e)
            {
                
                if (e.KeyCode == Keys.Enter)
                {
                    ServerSendMsg(txtSendMsg.Text.Trim());
               }
            }
    }
    

    Result:

    Hope my solution could be helpful.

    Best regards,

    Jack





    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, September 11, 2019 8:49 AM
  • Thanks Jack

    According to your solution, i think my problem is related to threading problem. i see you are using this code :

    TextBox.CheckForIllegalCrossThreadCalls = false;

    I've use this code in my FrmChatItem form but my problem was not solved!

    Any idea?

    thanks in advance


    http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx

    Wednesday, September 11, 2019 10:29 AM
  • My penny's worth - why reinvent the wheel. SignalR is just a NuGet package from Microsoft, a hub class and some client code. Ten minutes tinkering and you're done. They cover everything from outages, reconnecting, etc.

    Below is an example the search tool found for me. This is community content so the usual caveats and conditions apply, about checking the source code and referenced libraries.

    https://code.msdn.microsoft.com/windowsdesktop/Using-SignalR-in-WinForms-f1ec847b

    SignalR is well established and produced by Microsoft, so use that as a jumping stone to further reading. 

    All the best,
    Pete


    #PEJL
    Got any nice code? If you invest time in coding an elegant, novel or impressive answer on MSDN forums, why not copy it over to TechNet Wiki, for future generations to benefit from! You'll never get archived again, and you could win weekly awards!

    Have you got what it takes to become this month's TechNet Technical Guru? Join a long list of well known community big hitters, show your knowledge and prowess in your favoured technologies!


    Wednesday, September 11, 2019 12:55 PM
    Moderator
  • Hi Hamed_1983,

    Actually you are using Async method to receive data. So, it will be a different thread and the best approach is using Invoke method of text box as described here.


    Avik Das

    Wednesday, September 11, 2019 1:05 PM
  • Hi again!
    To demonstrate what's happen in my app, i've make a simple sulotion which consist of 4 projects.

    <MOD REDACTED> (although it was broken anyway) - Please only raw code on GitHub, thanks.

    To test the app, do the following steps :
    1. Run Houshmand.ConfigManager.DemoServer.exe & Press start button to listen on default ip & port!
    2. Run Houshmand.ConfigManager.DemoClient.exe & Press connect button to connect to server app (after you've connected to server, you must see clients list in datagridView, if not, plz click on 'Refresh clients list' button to refresh connected clients)
    3. Run step 2 multiple time to connect more clients to server app.
    4. Now if you click on each ConnectionID in dataGridView, a new 'FrmChatItem' has open to enter chat & send data to destination client.
    5. if you send a message to destination client, it also show up 'FrmChatItem' form to start incoming chat, but in this step, you're facing problem! the 'FrmChatItem' object hanging!!!


    http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx




    • Edited by Hamed_1983 Wednesday, September 11, 2019 3:21 PM
    • Edited by Pete LakerMVP, Moderator Wednesday, September 11, 2019 11:51 PM removed broken link, not sure why hoster removed their files in the first place
    Wednesday, September 11, 2019 3:19 PM
  • Codes are not getting downloaded.

    Avik Das

    Wednesday, September 11, 2019 7:27 PM
  • This is new <MOD REDACTED>


    http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx



    Wednesday, September 11, 2019 7:48 PM
  • Sorry to remove your RAR link. RAR files have had vulnerabilities like running code or extracting viruses from within images, after the extraction completes. We just can't share libraries, compiled exes, or use file formats that expose a risk to others. It's not you, it's a general stance we are having to take in these trickier times. Please upload unzipped to GitHub and do not share compiled code.

    Thanks,
    Pete


    #PEJL
    Got any nice code? If you invest time in coding an elegant, novel or impressive answer on MSDN forums, why not copy it over to TechNet Wiki, for future generations to benefit from! You'll never get archived again, and you could win weekly awards!

    Have you got what it takes to become this month's TechNet Technical Guru? Join a long list of well known community big hitters, show your knowledge and prowess in your favoured technologies!

    Wednesday, September 11, 2019 11:49 PM
    Moderator
  • Hi again!

    I don't know gitHub very good. However, i've create zip file & upload to gitHub, plz check this link.


    http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx

    Thursday, September 12, 2019 7:49 AM
  • Hi Hamed_1983,

    You need to change another line in FrmDemoClient.cs.

    this.OpenOrUpdateChatSession(e.CmdResult.Command.FromConnectionID, e.CmdResult.Result.ToString());

    change to -

    this.Invoke(new Action(() => { 
        this.OpenOrUpdateChatSession(e.CmdResult.Command.FromConnectionID, e.CmdResult.Result.ToString());
    }));

    Hope it will work. May not be a best solution; but it should work for you.


    Avik Das

    • Marked as answer by Hamed_1983 Thursday, September 12, 2019 8:54 PM
    Thursday, September 12, 2019 7:52 PM
  • Thanks Avik

    It works!!


    http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx

    Thursday, September 12, 2019 8:54 PM