?
Solved

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

Posted on 2004-11-19
24
Medium Priority
?
254 Views
Last Modified: 2010-04-15
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 ();
                  }
      
            }
      }
}
0
Comment
Question by:Tom Knowlton
  • 16
  • 6
23 Comments
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12631143
Here is my source code ZIPPED if it helps:

http://www.robotzgame.com/junk/robotz.zip
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12631158
My bad:

The link to my test application code is:

http://www.robotzgame.com/junk/TestSocket.zip
0
 
LVL 1

Expert Comment

by:adambutt
ID: 12631882
Are you running the same application on both computers?
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12635780
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.
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12636289
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.
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12636294
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.
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12636296
Here is the link to the question that answered THIS question as well.

http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_21213983.html
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 12637003
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.
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12645703
You mean like the UpdateText( ) method......or what are you talking about?
0
 
LVL 9

Accepted Solution

by:
Joeisanerd earned 2000 total points
ID: 12646326
in your client class you would add an event handler like this

namespace WindowsApplicationTestSocket
{
     namespace ClassLibraryServerClient
     {
          public delegate void DataReceivedEventHandler(string message);
          /// <summary>
          /// Summary description for Client.
          /// </summary>
          public class Client
          {
               public event DataReceivedEventHandler OnDataReceived;
               ....
               /*Methods blah blah */

             
           // Then inside your data received method you would call the OnDataReceived method if it is not = to null
               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 ();
               }

then in your main app you subscribe the event from your instantiated client class
classname.OnDataReceived += new DataReceivedEventHandler(Form1_DataReceived);



0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12646738
public event          ....   so event is a TYPE    ????
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12646966
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 ();
                  }
      
            }
      }
}
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12647093
I forgot to declare the delegate......ooops.......
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12648025
Joe:

The points are yours........but I ask that you help me troubleshoot the implementation of delegates and help me wire it up properly.
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 12648612
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);
      }
}
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12648668
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.
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 12648683
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.
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 12648686
sorry I just posted the wrong comment to the wrong post
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12648693
I am not using a DataGrid.
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12648698
Gotcha....you had me wondering!!!!
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 12648828
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
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12648891
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.
0
 
LVL 5

Author Comment

by:Tom Knowlton
ID: 12648930
Joe:

All I need is someone to tweak the code so it works:

http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_21216377.html
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
The video will let you know the exact process to import OST/PST files to the cloud based Office 365 mailboxes. Using Kernel Import PST to Office 365 tool, one can quickly import numerous OST/PST files to Office 365. Besides this, the tool also comes…
Watch the video to learn how one can deal with PST file corruption issue with an outstanding Kernel for Outlook PST Repair Tool easily. Using this tool, non-technical users can swiftly perform the repair process to restore their essential data witho…
Suggested Courses

600 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question