Jump to content

Sockets Server/Client ?

- - - - -

  • Please log in to reply
1 reply to this topic

#1
amw_drizz

amw_drizz

    Newbie

  • Members
  • Pip
  • 1 posts
Alright, This is my first post here and to open with a question.

I currently have a console app, that does two things. First is spawns a server and accepts connections on a specific port. Second it manages an external program using System.Diagnostics. For the most part it works as intended, except that on occasion it socket server will lock up and refuse new connections.

As is I need to figure out how to add in a new 'feature/function' to the socket server to simulate a console/terminal like feel to the end user. Right now, as it sits I do use async calls on the server side, but I am thinking they are not effective as they can cause lock ups. As I can only either send or receive a single line at a time. Cannot send and receive at the same time, which for my new feature/function I need to be able to do.

This is what I am working with and am open to all suggestions other than port over to C++ and write/roll my own socket api. (not experienced enough for that)

        

public static void ReceiveCallback(IAsyncResult AsyncCall)

        {

            allDone.Set();

            DateTime Expir = DateTime.Now.AddSeconds(20);

            // Data is send in bytes -- so we need to convert a C# string to a Byte[]

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

            Byte[] message = encoding.GetBytes("MWrap API Server v" + Program.ver+"\n\r");

            Byte[] message2 = encoding.GetBytes("Build: " + Program.Bver+"\n\r");

            // Program p = new Program();

            // The original listening socket is returned in the AsyncCall, we need to call "EndAccept" to

            // receive the client socket which we can use to send and receive data.

            Socket listener = (Socket)AsyncCall.AsyncState;

            Socket client = listener.EndAccept(AsyncCall);

            client.ReceiveTimeout = 20000;

            // listener.BeginAccept(new AsyncCallback(ReceiveCallback), listener);

            Stream S = new NetworkStream(client);

            StreamReader sr = new StreamReader(S);

            StreamWriter sw = new StreamWriter(S);

            

            // Console.WriteLine("Received Connection from {0}", client.RemoteEndPoint);

            client.Send(message);

            client.Send(message2);

            // End of the incoming connection

            bool test = true; // Used for Inner While Loop Set to false from within after client.Close() to break full connection and disconnect client

            while (client.Connected)

            {

               // Read lines until client tells us to stop

                while (test == true)

                {

                    string output = null;

                    try

                    {

                        output = sr.ReadLine().ToString();

                        // Console.WriteLine(output);

                    }

                    catch

                    {

                        // if the output (IE sent data to us is NULL) close the connection

                        test = false;

                        client.Close();

                        break;

                    }

                    

                   

                    // Replacing IF statments with a Switch Statment

                    switch (output.ToLower())

                    {

                        // All accepted commands here

                        default:

                            Send(client, "INVALID");

                            break;

                    }

                }

            }

            // Console.WriteLine("Ending the connection");

            try

            {

                if (client.Connected == true)

                {

                    client.Disconnect(false);

                    client.Close();

                }

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Data.ToString());

            }

            //client.Close();

            

            // At the end of the connection, we need to tell the OS that we can receive another call

            

        }

        [STAThread]

        public static void Main()

        {

            //api_server api = new api_server();

            Program.ReloadServerProperties();

            start_listen();

        }

        public static byte[] ConvertToString(string input)

        {

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

            Byte[] message = encoding.GetBytes(input+"\n\r");

            return message;

        }

        static ManualResetEvent allDone = new ManualResetEvent(false);


        static void start_listen()

        {

            try

            {


                IPAddress localAddress = IPAddress.Parse("0.0.0.0");

                

                // Define the kind of socket we want: Internet, Stream, TCP

                Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


                // Define the address we want to claim: the first IP address found earlier, at port 2200

                IPEndPoint ipEndpoint = new IPEndPoint(localAddress, port);


                // Bind the socket to the end point

                listenSocket.Bind(ipEndpoint);


                // Start listening, only allow 1 connection to queue at the same time

                listenSocket.Listen(100);

                //listenSocket.BeginAccept(new AsyncCallback(ReceiveCallback), listenSocket);

                Console.WriteLine("API Server Created {0}", listenSocket.LocalEndPoint);

                Console.WriteLine("Your External IP Address is: " + getPublicIP());

                Console.WriteLine("Your Local IP is: " + localIP() );


                // Start being important while the world rotates

                while (true) // Required for Keep ALive

                {

                    allDone.Reset();

                    listenSocket.BeginAccept(new AsyncCallback(ReceiveCallback), listenSocket);

                    allDone.WaitOne();

                    //Thread.Sleep(2000);

                } 


            }

            catch (Exception e)

            {

                Console.WriteLine("Caught Exception: {0}", e.ToString());

            }

        }


The following two functions is what sends data back to the connected client


        static void Send(Socket Client, string msg){

            byte[] ms = ConvertToString(msg);

            Client.Send(ms);

            //Client.BeginSend(ms, 0,ms.Length, 0, new AsyncCallback(SendCallBack), Client);

        }


        static void SendCallBack(IAsyncResult ar)

        {

            try

            {

                Socket client = (Socket)ar.AsyncState;

                int bytesSent = client.EndSend(ar);

                allDone.Set();

            }

            catch (Exception e)

            {

                Console.WriteLine(e.ToString());

            }

        }


So quick summery, Need to be able to continue receiving data from client while also sending data to the client as well. I've thought about using two seperate sockets, one to send and one to receive but was unsure of how to terminate the continuous send back to the client of the console output.

IE would something like this work?

public static bool consoleProc = true;

...

while(consoleProc == true){

// send data back

}


// On another connection

case "stopconsole": // receive stop command and change the public bool to false and on the next loop the stream will stop

consoleProc = false;

break;


Thanks for the help, Jon

#2
sam_coder

sam_coder

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 372 posts
there should be no need to stop sending to receive. Sockets are bidirectional.

As soon as the client connects to the server, the server can BeginReceive. And every time it receives data, if can call BeginReceive again.

Similarly, on the client side, after it establishes the connection, it can do that same pattern, BeginReceive on the server, and on each callback, just call BeginReceive again.

You follow?




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users