Link to home
Start Free TrialLog in
Avatar of Tom Knowlton
Tom KnowltonFlag for United States of America

asked on

URGENT 500 POINTS!!! I just don't get Sockets :(

Why do I have to CLICK multiple times in order to get the message to show up?


FORM CODE:


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplicationTestSocket
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            private WindowsApplicationTestSocket.ClassLibraryServerClient.Server sv = new WindowsApplicationTestSocket.ClassLibraryServerClient.Server();
            private System.Windows.Forms.Button button1;
            public System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.TextBox textBox2;
            private WindowsApplicationTestSocket.ClassLibraryServerClient.Client client = new WindowsApplicationTestSocket.ClassLibraryServerClient.Client();

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();                  
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.button1 = new System.Windows.Forms.Button();
                  this.textBox1 = new System.Windows.Forms.TextBox();
                  this.textBox2 = new System.Windows.Forms.TextBox();
                  this.SuspendLayout();
                  //
                  // button1
                  //
                  this.button1.Location = new System.Drawing.Point(136, 80);
                  this.button1.Name = "button1";
                  this.button1.TabIndex = 0;
                  this.button1.Text = "button1";
                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  //
                  // textBox1
                  //
                  this.textBox1.Location = new System.Drawing.Point(32, 136);
                  this.textBox1.Name = "textBox1";
                  this.textBox1.Size = new System.Drawing.Size(240, 20);
                  this.textBox1.TabIndex = 1;
                  this.textBox1.Text = "textBox1";
                  //
                  // textBox2
                  //
                  this.textBox2.Location = new System.Drawing.Point(24, 40);
                  this.textBox2.Name = "textBox2";
                  this.textBox2.Size = new System.Drawing.Size(240, 20);
                  this.textBox2.TabIndex = 2;
                  this.textBox2.Text = "textBox2";
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(292, 273);
                  this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                                              this.textBox2,
                                                                                                              this.textBox1,
                                                                                                              this.button1});
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.Load += new System.EventHandler(this.Form1_Load);
                  this.ResumeLayout(false);
            }

            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  Application.Run(new Form1());
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
                  
                  client.SendData(this.textBox2.Text);      
                  Application.DoEvents();
                  textBox1.Text = sv.txtReceived;                                    
                  sv.txtReceived = "0";                  
            }

            private void Form1_Load(object sender, System.EventArgs e)
            {
                  sv.StartListening();
                  client.Connect();                  
            }
      }
}





SERVER CLASS:


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Net;
using System.Net.Sockets;


namespace WindowsApplicationTestSocket
{
      namespace ClassLibraryServerClient
      {
            /// <summary>
            /// Summary description for Class1.
            /// </summary>
            public class Server
            {
                  public AsyncCallback pfnWorkerCallBack;
                  public  Socket m_socListener;
                  public  Socket m_socWorker;

                  public string txtReceived="";

                  public Server()
                  {                  
                  }


                  public void StartListening()
                  {
                        try
                        {
                              //create the listening socket...
                              m_socListener = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);            
                              IPEndPoint ipLocal = new IPEndPoint ( IPAddress.Any ,8221);
                              //bind to local IP Address...
                              m_socListener.Bind( ipLocal );
                              //start listening...
                              m_socListener.Listen (4);
                              // create the call back for any client connections...
                              m_socListener.BeginAccept(new AsyncCallback ( OnClientConnect ),null);
                              //cmdListen.Enabled = false;

                        }
                        catch(SocketException se)
                        {
                              //                        MessageBox.Show ( se.Message );
                        }
                  }

                  public void OnClientConnect(IAsyncResult asyn)
                  {
                        try
                        {
                              m_socWorker = m_socListener.EndAccept (asyn);
                              
                              WaitForData(m_socWorker);
                        }
                        catch(ObjectDisposedException)
                        {
                              System.Diagnostics.Debugger.Log(0,"1","\n OnClientConnection: Socket has been closed\n");
                        }
                        catch(SocketException se)
                        {
                              //MessageBox.Show ( se.Message );
                        }
                  
                  }
                  public class CSocketPacket
                  {
                        public System.Net.Sockets.Socket thisSocket;
                        public byte[] dataBuffer = new byte[1];
                  }

                  public void WaitForData(System.Net.Sockets.Socket soc)
                  {
                        try
                        {
                              if  ( pfnWorkerCallBack == null )
                              {
                                    pfnWorkerCallBack = new AsyncCallback (OnDataReceived);
                              }
                              CSocketPacket theSocPkt = new CSocketPacket ();
                              theSocPkt.thisSocket = soc;
                              // now start to listen for any data...
                              soc .BeginReceive (theSocPkt.dataBuffer ,0,theSocPkt.dataBuffer.Length ,SocketFlags.None,pfnWorkerCallBack,theSocPkt);
                        }
                        catch(SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }

                  }

                  public void OnDataReceived(IAsyncResult asyn)
                  {
                        try
                        {
                              CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState ;
                              //end receive...
                              int iRx  = 0 ;
                              iRx = theSockId.thisSocket.EndReceive (asyn);
                              char[] chars = new char[iRx +  1];
                              System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                              int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
                              System.String szData = new System.String(chars);
                              //txtDataRx.Text = txtDataRx.Text + szData;
                              this.txtReceived += szData[0];
                              WaitForData(m_socWorker);                              

//                              WindowsApplicationTestSocket.Form1.ActiveForm.Controls[0].Text += szData;
                        }
                        catch (ObjectDisposedException)
                        {
                              System.Diagnostics.Debugger.Log(0,"1","\nOnDataReceived: Socket has been closed\n");
                        }
                        catch(SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }
                  }

                  public void TransferMessage()
                  {
                        try
                        {
                              Object objData = txtReceived;
                              byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString ());
                              m_socWorker.Send (byData);
                        }
                        catch(SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }
                  }
            
            }
      }
}




CLIENT CLASS:


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Net.Sockets ;


namespace WindowsApplicationTestSocket
{
      namespace ClassLibraryServerClient
      {
            /// <summary>
            /// Summary description for Client.
            /// </summary>
            public class Client
            {
                  Socket m_socWorker;
                  public string txtReceived="";

                  public Client()
                  {
                        //
                        // TODO: Add constructor logic here
                        //
                  }

                  public void Connect()
                  {
                        try
                        {
                              //create a new client socket ...
                              m_socWorker = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                              //String szIPSelected  = txtIPAddress.Text;
                              String szIPSelected  = "192.168.0.155";
                              //String szPort = txtPort.Text;
                              String szPort = "8221";
                              int  alPort = System.Convert.ToInt16 (szPort,10);
                  
                              System.Net.IPAddress      remoteIPAddress       = System.Net.IPAddress.Parse(szIPSelected);
                              System.Net.IPEndPoint      remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, alPort);
                              m_socWorker.Connect(remoteEndPoint);
                        }
                        catch (System.Net.Sockets.SocketException se)
                        {
                              //MessageBox.Show ( se.Message );
                        }
                  }
                  

                  public void SendData(string newmessage)
                  {
                        try
                        {
                              Object objData = newmessage;
                              byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
                              m_socWorker.Send (byData);
                        }
                        catch(System.Net.Sockets.SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }
                  }

                  public void ReceiveData()
                  {
                        try
                        {
                              byte [] buffer = new byte[1024];
                              int iRx = m_socWorker.Receive (buffer);
                              char[] chars = new char[iRx];

                              System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                              int charLen = d.GetChars(buffer, 0, iRx, chars, 0);
                              System.String szData = new System.String(chars);
                              //txtDataRx.Text = szData;
                              txtReceived = szData;
                        }
                        catch(System.Net.Sockets.SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }
                  }

                  public void StopClient()
                  {
                        m_socWorker.Close ();
                  }
      
            }
      }
}
Avatar of Tom Knowlton
Tom Knowlton
Flag of United States of America image

ASKER

Here is my source code ZIPPED if it helps:

http://www.robotzgame.com/junk/robotz.zip
My bad:

The link to my test application code is:

http://www.robotzgame.com/junk/TestSocket.zip
Avatar of adambutt
adambutt

Are you running the same application on both computers?
I am running a single Windows application which has 2 classes in it:  Server.cs    and Client.cs.

I instantiate objects for both the server and the client class.

Then I start the server object to listen for attempts to connect.

Then I have the client object send a message when I click the button on the form.

The problem is the message does not show up until I click the button several times.
The problem has been solved in the interim.

I am going to ask CS to close this question and mark it as PAQ.


The solution is posted below.
The following post....in another related question......also answered this question:

[[from Expert esorf ]]

In general, it's a thread synchronization issue.  The problem is that your socket listener is working on another thread.  Your display logic (textBox1.Text =) happens before the server has received the entire string.

Add a method in your Form1 called UpdateText() which has the line
               textBox1.Text = sv.txtReceived;

Then within your server OnDataReceived() method, after the line
                         txtReceived = txtReceived + szData;
add a call to the updateText method
                         myform.UpdateText();

This way, the text box value will be updated as each new character comes in.

There are many ways to generalize this solution, but this should get you started.
Eventhough you are closing the question this might help. I created a simple client server class and what you need for generalizatoin is for the client and server objects to throw events that your forms can "subscribe" to just like the OnLoad and OnInit and other events subscribe to events.
You mean like the UpdateText( ) method......or what are you talking about?
ASKER CERTIFIED SOLUTION
Avatar of Joeisanerd
Joeisanerd

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
public event          ....   so event is a TYPE    ????
I am still doing something wrong:

I get the error:  The type or namespace name 'DataReceivedEventHandler' could not be found (are you missing a using directive or an assembly reference?)


NEW CLIENT CLASS CODE:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Net.Sockets ;


namespace WindowsApplicationTestSocket
{
      namespace ClassLibraryServerClient
      {
            /// <summary>
            /// Summary description for Client.
            /// </summary>
            public class Client
            {
                  Socket m_socWorker;
                  public string txtReceived="";
                  public event DataReceivedEventHandler OnDataReceived;

                  public Client()
                  {
                        //
                        // TODO: Add constructor logic here
                        //
                  }

                  public void Connect()
                  {
                        try
                        {
                              //create a new client socket ...
                              m_socWorker = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                              //String szIPSelected  = txtIPAddress.Text;
                              String szIPSelected  = "192.168.0.155";
                              //String szPort = txtPort.Text;
                              String szPort = "8221";
                              int  alPort = System.Convert.ToInt16 (szPort,10);
                  
                              System.Net.IPAddress      remoteIPAddress       = System.Net.IPAddress.Parse(szIPSelected);
                              System.Net.IPEndPoint      remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, alPort);
                              m_socWorker.Connect(remoteEndPoint);
                        }
                        catch (System.Net.Sockets.SocketException se)
                        {
                              //MessageBox.Show ( se.Message );
                        }
                  }
                  

                  public void SendData(string newmessage)
                  {
                        try
                        {
                              Object objData = newmessage;
                              byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
                              m_socWorker.Send (byData);
                        }
                        catch(System.Net.Sockets.SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }
                  }

                  public void ReceiveData()
                  {
                        try
                        {
                              byte [] buffer = new byte[1024];
                              int iRx = m_socWorker.Receive (buffer);
                              char[] chars = new char[iRx];

                              System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                              int charLen = d.GetChars(buffer, 0, iRx, chars, 0);
                              System.String szData = new System.String(chars);
                              //txtDataRx.Text = szData;
                              txtReceived = szData;

                              if( OnDataReceived != null )
                                    OnDataReceived( txtReceived );
                        }
                        catch(System.Net.Sockets.SocketException se)
                        {
                              //MessageBox.Show (se.Message );
                        }
                  }

                  public void StopClient()
                  {
                        m_socWorker.Close ();
                  }
      
            }
      }
}
I forgot to declare the delegate......ooops.......
Joe:

The points are yours........but I ask that you help me troubleshoot the implementation of delegates and help me wire it up properly.
Did you need help wiring it up to the main form? or are you talking about your socket class?

What I did as well is write a OnConnect and OnDisconnect event handler that is called from the respective functions. In your client connect method you should have it do it asynchronously like the server does for the ondatareceive method. Then in your client connect callback function you can call the OnConnect event handler (you have to set that up).

To tell if the client has disconnected you need to handle that in your DataReceived callback function and check for a null socket.

Here is what a connect callback for the client would look like

private void OnConnectCallBack(IAsyncResult ar)
{
      try
      {
            Socket sock = (Socket) ar.AsyncState;
                  
            if( sock.Connected )
            {
                  connected = true; // class variable
                  // Setup the ReceiveDataCallBack function, which has the signature as this callback function
                  sock.BeginReceive( receivedBytes, 0, receivedBytes.Length, SocketFlags.None,
                        new AsyncCallback(ReceiveDataCallBack), sock);
                              
                  IPEndPoint remote = (IPEndPoint)sock.RemoteEndPoint;
                  // RemoteSocketEventArgs is my own EventHandler Args class
                  if( OnConnect != null )
                        OnConnect(new RemoteSocketEventArgs(
                              remote.Address.ToString(),
                              remote.Port));
            }
      }
      catch(Exception ex)
      {
            connected = false;
            throw new Exception(ex.Message);
      }
}
Joe:

How much of an inconvenience would it be for you to download my source code, get it working, then send it back?

I would be happy to re-post your changes HERE in EE so that others may benefit.

What I am looking for is a stand-alone CLIENT class, and a stand-alone SERVER class that I can invoke.........and have them talk to each other from different applications.
is it really necessary to refresh the entire grid on cancel since you already set the DataSet up in the page load event? Instead how about call the DataGrid DataBind() from the cancel command function.
sorry I just posted the wrong comment to the wrong post
I am not using a DataGrid.
Gotcha....you had me wondering!!!!
You can do what I did, search the web and educate yourself on what is really involved.

Ultimately what I did was createa one class file with a TcpClientSocket and a TcpServerSocket class.  This dll would be referenced in the apps that need them. If it is a chat program then you might use a client and server object for the cleint app and just a server object on the server part.

There are articles on thecodeproject.com that can help
http://www.codeproject.com/csharp/asyncsockets2.asp

if you have specified questiosn then ask them in EE, otherwise I don't really want to write your code from start to finish
Joe:

I don't want you to write my code for me either.

I would ask my questions if I knew what to ask and how to ask it.