Resolved Socket Programming

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
Hey,
I took the asynchorous example from Windows.
This is my Code
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SVS_Console
{
    // State object for receiving data from remote device. 
    public class StateObject
    {
        // Client socket. 
        public Socket workSocket = null;
        // Size of receive buffer. 
        public const int BufferSize = 256;
        // Receive buffer. 
        public byte[] buffer = new byte[BufferSize];
        // Received data string. 
        public StringBuilder sb = new StringBuilder();
    }

    public class AsynchronousClient
    {
        // The port number for the remote device. 
        private const int port = 1023;

        // ManualResetEvent instances signal completion. 
        private static ManualResetEvent connectDone =
            new ManualResetEvent(false);
        private static ManualResetEvent sendDone =
            new ManualResetEvent(false);
        private static ManualResetEvent receiveDone =
            new ManualResetEvent(false);

        // The response from the remote device. 
        private static String response = String.Empty;

        private static void StartClient()
        {
            // Connect to a remote device. 
            try
            {
                // Establish the remote endpoint for the socket. 
                // The name of the   
                // remote device is "host.contoso.com". 
                IPHostEntry ipHostInfo = Dns.GetHostEntry("192.168.4.15");
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

                // Create a TCP/IP socket. 
                Socket client = new Socket(ipAddress.AddressFamily,
                    SocketType.Stream, ProtocolType.Tcp);
                Console.WriteLine("Connecting to Datalogic device " + ipAddress + "");
                // Connect to the remote endpoint. 
                client.BeginConnect(remoteEP,
                    new AsyncCallback(ConnectCallback), client);
                connectDone.WaitOne();

                Console.WriteLine("Press To Send Command For Host Mode Programming To The System");
                Console.ReadLine();
                // Send test data to the remote device. 
                Send(client, "\0C\r\n");
                sendDone.WaitOne();
                Console.WriteLine("Press to receive");
                // Receive the response from the remote device. 
                Receive(client);
                receiveDone.WaitOne();

                // Write the response to the console. 
                Console.WriteLine("Response received : {0}", response);


                Console.ReadLine();
                Console.WriteLine("Did you read Response?");


                // Release the socket. 
               // client.Shutdown(SocketShutdown.Both);
              //  client.Close();

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

        private static void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object. 
                Socket client = (Socket)ar.AsyncState;

                // Complete the connection. 
                client.EndConnect(ar);

                Console.WriteLine("Socket connected to {0}",
                    client.RemoteEndPoint.ToString());

                // Signal that the connection has been made. 
                connectDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void Receive(Socket client)
        {
            try
            {
                // Create the state object. 
                StateObject state = new StateObject();
                state.workSocket = client;

                // Begin receiving the data from the remote device. 
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the state object and the client socket   
                // from the asynchronous state object. 
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;

                // Read data from the remote device. 
                int bytesRead = client.EndReceive(ar);

                if (bytesRead > 0)
                {
                    // There might be more data, so store the data received so far. 
                    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                    // Get the rest of the data. 
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    // All the data has arrived; put it in response. 
                    if (state.sb.Length > 1)
                    {
                        response = state.sb.ToString();
                    }
                    // Signal that all bytes have been received. 
                    receiveDone.Set();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void Send(Socket client, String data)
        {
            // Convert the string data to byte data using ASCII encoding. 
            byte[] byteData = Encoding.ASCII.GetBytes(data);

            // Begin sending the data to the remote device. 
            client.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), client);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object. 
                Socket client = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device. 
                int bytesSent = client.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to server.", bytesSent);

                // Signal that all bytes have been sent. 
                sendDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static int Main(String[] args)
        {
            StartClient();
            return 0;
        }
    }
}
I have put a ConsoleReadLine after receiving the response from the remote device.
C#:
Receive(client);
receiveDone.WaitOne();
                // Write the response to the console. 
                Console.WriteLine("Response received : {0}", response);
Nothing is coming back when i am replying in Hercules. I am sending this back for testing (below)

1583765585270.png


Basically once i send <ESC>C i will be receiving back <ESC>H<CR><LF>. Once i receive that i need to check, then send another command <ESC>B, and i then receive a <ESC>S<CR><LF> back. Once i have that, i then send another command then i need to read the strings coming back after that and count them if possible.

Cheers
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
Did you set a breakpoint on ReceiveCallback()? Is it even being called?
 

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
Inserted breakpoint and its behaving the same.Ah i figured this part would call the receive back from receive


sendDone.WaitOne();
Console.WriteLine("Press to receive");
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
So is your breakpoint being hit?
 

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
Breakpoijt is turning red circle when enabling but not hitting (doing anything). Going to check if I have it in debug mode and check debug settings. The code looks ok so I cant srr why it's not showing the results... argh..
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
When you place the red dot on whatever line you want to step into the code -on-, this is only a break point, and upon that code ever being reached, your program will pause and your debugger will indicate with a yellow arrow mark; indicating that line has been reached by whatever calling code called it. And upon this step, you need to press F11 to step through the code! There is a debug tutorial in my signature, which you can avail and benefit from.

This example screenshot shows the break point placed but not reached.

Screenshot_83.jpg


This example screenshot shows the break point has been placed and also reached.

Screenshot_84.jpg
 
Last edited:

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
Step through the callback and see the values of the variables...
 

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
Sorry for my stupidity.
I cant see what its not getting my replies backk

If i comment out the below the code runs through, obviously no reply. If its in the program, it is waiting on the reply but not getting the replies back.
I've looked through the program again on microsoft and cannot see any glaring differences... argh

C#:
 // Receive the response from the remote device. 
                Receive(client);
                receiveDone.WaitOne();



                // Write the response to the console. 
                Console.WriteLine("Response received : {0}", response);


// Write the response to the console.
Console.WriteLine("Response received : {0}", response);


Something must be wrong at this part... but i cant figure out what

C#:
 private static void Receive(Socket client)
        {
            try
            {
                // Create the state object. 
                StateObject state = new StateObject();
                state.workSocket = client;

                // Begin receiving the data from the remote device. 
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void ReceiveCallback(IAsyncResult ar)
        
        {
            try
            {
              
                // Retrieve the state object and the client socket   
                // from the asynchronous state object. 
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;

                // Read data from the remote device. 
                int bytesRead = client.EndReceive(ar);

                if (bytesRead > 0)
                {
                    // There might be more data, so store the data received so far. 
                    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                    // Get the rest of the data. 
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    // All the data has arrived; put it in response. 
                    if (state.sb.Length > 1)
                    {
                        response = state.sb.ToString();
                    }
                    // Signal that all bytes have been received. 
                    receiveDone.Set();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
I didn't link this in my signature for fun : Navigate code with the debugger - Visual Studio and then tell you to read it so you can identify what is going on in your project.

Just aside note :

C#:
.WaitOne();
According to the docs :
WaitOne()Blocks the current thread until the current WaitHandle receives a signal.
WaitHandle.WaitOne Method (System.Threading) - If cancelling out that line helps, then that means something is likely blocking your calling code. Only by debugging will you find what that is. Nobody but you can do that for you.

Something else is you shouldn't be writing your manual reset events with the hardcoded false boolean, but instead you would be recommended to use Get;Setters; instead. :
C#:
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
Despite that Microsoft themselves actually provide the documentation as you have followed and not as I have recommended changing too may also cause you some issues. The idea of the ManualResetEvent is that you are in control of setting when and how the reset event is called. Also note the docs also say the following :
Pressing the Enter key again causes the example to call the Reset method and to start one more thread, which blocks when it calls WaitOne. Pressing the Enter key one final time calls Set to release the last thread, and the program ends.
See the docs regarding that quote : ManualResetEvent Class (System.Threading)

Lastly, read that debug link that I linked and then start stepping into your code, checking everything that currently executes. Note; if any of your calling code is told to keep polling up other methods while one executes, you will need to set a break point on those other methods too so the debugger can catch when they also fire... There are other issues I can see with the example you provided, but there is only so much advice I can give you, and all of which would be evident to you if you actually debugged your code.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
But a break point on line 33. Are you receiving data?
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
One more thing regarding the reset event : 5 Minutes Guide of ManualResetEvent - Read that regarding the comments I made on post 29. While there may be some other devs here who disagree with not following the default documentation, it should become clear while reading that article. Re this snipped why I do it a little differently, which I will briefly explain below :
In the above code, we initialize the ManualResetEvent with false value, that means all the threads which calls the WaitOne method will block until some thread calls the Set() method.

If we initialize ManualResetEvent with true value, all the threads which calls the WaitOne method will not block and free to proceed further.
When I am not writing test/development code, I make a habit of using the : INotifyPropertyChanged Interface (System.ComponentModel) and if my method is polling, I can call to update the get setter of the boolean for the ManualResetEvent with the value of true, and then let the property changed interface take care of initiating the reset procedure and you can ensure .set() is called upon the property changing to true; thus calls on the reset event which will free up that thread for the next polling call.

I'm not recommending for one minute that you call set(), to free up the thread. You'd be better to identify what is holding the thread hostage and identify the source of the blockage from your calling code first.

I hope you find this information useful and more importantly, that you understand what I am advising you to do.
 

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
Hi Sheepings thanks for taking the time to help me out mate. I am going to run through the dubug now, to see if i can identify the issue and go through the rest of your comments. I will post how i get on. Cheers man
 

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
So synchronous was of course best for what i was trying to do.
Managing to get it sending strings, reading strings.
Just in process now of building the HEX commands for the <ESC> <CR> <LF>
 

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
I need to send the data in HEX so for example.
I need to send 1b5b43 (<ESC>[C) i converted the string to bytes but its just showing as literally 1b5b43 on hercules. Anyone help?

C#:
 // string input = @"<ESC>[C";
            string input = @"1b5b43";
            byte[] encode = Encoding.UTF8.GetBytes(input);
            string result = ConnectServerAndGetResultByInput(input);
            if (string.Compare(@"<ESC>H<CR><LF>", result, true) == 0)
            {
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
A lot of your problems seems to stem from a lack of understanding of characters, strings, and encodings. 1b 4b 53 are already the hex values of the bytes you want to send.

For some reason, you made a string "1b4b53", and asked the framework to get the bytes representing that string. That would result in the hex bytes 31 62 34 62 35 33. It is these bytes that you ended up sending, and so the terminal obviously converted those bytes back to ASCII.

I suggest reviewing the ASCII table yet again like @Sheepings had told you to study last time.
 
Last edited:

tdignan87

Well-known member
Joined
Jul 8, 2019
Messages
93
Programming Experience
Beginner
Thanks for all your help. It's ok now, From reading skydivers comments i realised where i was going wrong. Appreciated
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
@Sheepings was actually directing you the right path. Maybe you just needed to hear the same thing phrased in a different way. Where as he is my good virtual twin and tell you what you need in a nice progression and with respect to the learning student, I tend to be the evil twin who will be snarky and/or sarcastic and just pump information out in a fire hose.

Most people respond better to his style as compared to mine. Something about flies, honey and vinegar... 😜 Sometimes though my style puts just the right amount of challenge, to make the student go "I'm smarter than that. I'll show that crazy Skydiver." Personally, I'd rather be a student in Sheepings class.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
Maybe you just needed to hear the same thing phrased in a different way.
Or maybe they just wasn't paying attention to their own topic and what directions they were been given.
Personally, I'd rather be a student in Sheepings class.
That's very nice of you to say @Skydiver. I'm not very good at responding to posts like that about myself, lol so thank you. 🙏

I know this is where I am meant to say something nice back, but you know I've always had a problem with how expressive you are with your fire hose approach and when posting code examples. So when you said :
I tend to be the evil twin who will be snarky and/or sarcastic and just pump information out in a fire hose.
This is where we differ when it comes to presenting information on help forums. Were I write almost all of my own code for myself with everything conjoined (mostly with Linq and Lambda expressions) which makes it almost impossible for new beginners and intermediates to read, understand and find inline variables conjured up in methods using Lambda expressions. Which is why almost all of my code examples are written explicit and without the likes of Linq joinder and so forth -- Typically as Microsoft docs do with there examples.

The way I write code for users on a forum and how I answer questions is much more expressive than the way you do with your fire hose approach, which typically dumps the answers in-front of them but gives the user more to research.

We also differ in regards to how your code examples are often unexplained and most times without inline or external comments. So when you compare how we teach; I take into account how I started and what I found more helpful. I always found the more elaborate posts that explained a scenario or block of code to me to be much more helpful, than receiving a code dump with a block of code that I didn't understand how it worked or how it does what it does.

This often led me to ask more questions about the code I received, thus just makes you look like a help vampire when you really just want to learn more about what you've been given. So when I'm helping people on a board, I take into account how I felt when I started out many moons ago; and what types of answers I found more helpful. And on that note, I'd rather be in my class too! Lol No offence.

Anyway, as not to sidetrack despite being resolved :
Thanks for all your help. It's ok now, From reading skydivers comments i realised where i was going wrong. Appreciated
I'm still not sure what exactly was so different from what I said for you to do, that Skydiver explained clearer? Regardless, how did you resolve this issue and what was the cause if you truly did resolve it?

@tdignan87 - Please keep in mind, that I have a very high personal workload and I do try to be as diligent and explanatory in almost all of my replies on the forum. That's often hard to do with my time constraints. However I am here to help you. So if you find one of my replies doesn't quite explain or answer your topic. Tell me and I will try to elucidate on my previous replies as to try give you a better understanding on the directions I am giving you.
 
Top Bottom