Laden...

TCPIP Server / senden aus mehreren Codebereichen

Erstellt von Piotr vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.375 Views
P
Piotr Themenstarter:in
2 Beiträge seit 2009
vor 5 Jahren
TCPIP Server / senden aus mehreren Codebereichen

Hallo zusammen,

ich bin relativ unerfahren mit C#, muss trotzdem eine Anwendung programmieren. Im grossen und ganzen muss ich eine Art Gerätemanager programmieren, der Befehle von einem TCPIP Client entgegennimmt und diese beantwortet.

Der Gerätespezifische Teil bereitet mir keine Probleme, einen TCPIP Server habe ich bereits ebenfalls programmiert und ich kann von einem Client einfache Befehle schicken und antworten empfangen.

Nun kann man auf dem Gerät noch ein Programm starten. Der Start wird dem Client quittiert, soweit so gut. Nun verschickt das gerät, während das Programm läuft, noch laufend events. Bei jedem Event wird automatisch die Funktion RunProgramFunction() mit dem Status Parameter aufgerufen. In dieser Funktion möchte ich nun den jeweiligen Status ebenfalls an den Client senden. wie mache ich das, wenn die TCPIP Implementation in der Main() Klasse verwirklicht ist?

danke und gruss

Hier die (sehr) vereinfachten Klassen mit allen relevanten Codezeilen:

Program.cs


using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Threading;

namespace MyNamespace
{
	static class Program
	{
        static int serverPort = 9999;

        [STAThread]
		static void Main()
		{                   
            TCPServerSocket();
        }

        private static void TCPServerSocket()
        {
            Instrument MeinInstrument = new Instrument();
            Socket servSock = null;
            string chrSTX = "\x02"; // Start of Text
            string chrETX = "\x03"; // End of Text

            try
            {
                // Verwende explizit IPv4
                servSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // Assoziiert den Socket mit einem lokalen Endpunkt
                servSock.Bind(new IPEndPoint(IPAddress.Any, serverPort));

                // Versetzt den Socket in den aktiven Abhörmodus 
                servSock.Listen(BACKLOG);
                Console.WriteLine("Webserver running...");
            }
            catch (SocketException se)
            {
                Console.WriteLine(se.ErrorCode + ": " + se.Message);
                Environment.Exit(se.ErrorCode);
            }

            byte[] rcvBuffer = new byte[BUFSIZE];
            int bytesRcvd;

            // Lässt den Server in einer Endlosschleife laufen
            for (; ; )
            {
                Socket client = null;

                try
                {
                    client = servSock.Accept();

                    Console.WriteLine("Handling client at " + client.RemoteEndPoint + " - ");

                    // Empfange bis der client die Verbindung schließt, das geschieht indem 0
                    // zurückgegeben wird
                    int totalbytesEchoed = 0;
                    while ((bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None)) > 0)
                    {
                        string cmd = System.Text.Encoding.Default.GetString(rcvBuffer, 0, bytesRcvd);
                        Console.WriteLine("-> {0}", cmd);

                        byte[] bufferToSend;
                        string reply = chrSTX + "OK" + chrETX;
                        switch (cmd)
                        {
                            case "CONNECT":
                                reply = chrSTX + MeinInstrument.Connect().ToString().ToUpper() + chrETX;
                                bufferToSend = Encoding.ASCII.GetBytes(reply);
                                client.Send(bufferToSend, 0, reply.Length, SocketFlags.None);
                                break;
                            case "DISCONNECT":
                                MeinInstrument.Disconnect();                              
                                bufferToSend = Encoding.ASCII.GetBytes("OK");
                                client.Send(bufferToSend, 0, reply.Length, SocketFlags.None);
                                break;
                            case "HEIZUNG_AN":
                                MeinInstrument.HeizungAn();                             
                                bufferToSend = Encoding.ASCII.GetBytes(reply);
                                client.Send(bufferToSend, 0, reply.Length, SocketFlags.None);
                                break;
                            case "HEIZUNG_AUS":
                                MeinInstrument.HeizungAus();                               
                                bufferToSend = Encoding.ASCII.GetBytes(reply);
                                client.Send(bufferToSend, 0, reply.Length, SocketFlags.None);
                                break;
							case "RUN_PROGRAM":
                                MeinInstrument.RunProgram();                               
                                bufferToSend = Encoding.ASCII.GetBytes(reply);
                                client.Send(bufferToSend, 0, reply.Length, SocketFlags.None);
                                break;
                            default:
                                break;
                        }
                        totalbytesEchoed += reply.Length;
                    }
                    Console.WriteLine("echoed {0} bytes.", totalbytesEchoed);

                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    client.Close();
                }
            }
        }

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();
        private const int BUFSIZE = 32;
        private const int BACKLOG = 5;
    }
}

Instrument.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;


namespace MyNamespace
{

    public class Instrument
    {

        Socket servSock = null;
        // Verwende explizit IPv4
		
        /// <summary>
        /// the constructor of the console class
        /// </summary>
        /// 
        public Instrument()
        {
            
        }

        public bool Connect()
        {
            return true;
        }

        public void Disconnect()
        {

        }


        public int HeizungAn()
        {
			return 0;
        }

     
        public int HeizungAus()
        {
          return 0;
        }



        public int StartProgram()
        {
        // starte programm und exit
        return 0;    

        }



        /// <summary>
        /// processes the status messages that are sent from the instrument
        /// during a program is in progress.    
     
        /// Possible status of a started program.
        /// Running: Program is running.
        /// CycleNumber: Cycle number information
        /// Finished: Program finished successfully.
        /// Error: Program finished with an error.
        /// Exception: A inner exception occurred.
        /// Warning: A warning occured during program execution
        private void RunProgramFunction(xyz status, object obj)
        {
            switch (status)
            {
                case ProgramStatus.Error:
					// hier einen string via die im Hauptprogramm geöffnete TCPIP Verbindung senden                
                    break;

                case ProgramStatus.Finished:
                 // hier einen string via die im Hauptprogramm geöffnete TCPIP Verbindung senden    
                    break;

                case ProgramStatus.Running:
                  // hier einen string via die im Hauptprogramm geöffnete TCPIP Verbindung senden    
                    break;

                case ProgramStatus.Warning:
                  // hier einen string via die im Hauptprogramm geöffnete TCPIP Verbindung senden    
                    break;

                case ProgramStatus.Exception:
                  // hier einen string via die im Hauptprogramm geöffnete TCPIP Verbindung senden    
                    break;

                case ProgramStatus.CycleNumber:
                  // hier einen string via die im Hauptprogramm geöffnete TCPIP Verbindung senden    
                    break;

                default:    
                    break;
            }
        }

      

    }
}

16.807 Beiträge seit 2008
vor 5 Jahren

Funktion RunProgramFunction()

Methode. Funktionen haben nur funktionale Programmiersprachen.

Zum Problem:
Ich sehe zwar nirgends eine Stelle, die RunProgramFunction aufgruft; aber natürlich muss an der Stelle die Verbindung zum Client bekannt sein.
Danach kannst Du über die Verbindung eben etwas an den Client schicken.
client.Send() verwendest Du ja bereits an anderen Stellen.

PS: ich hoffe der Code ist nur für Dich; nicht für Kunden 😃

P
Piotr Themenstarter:in
2 Beiträge seit 2009
vor 5 Jahren

hinter dem Instrumenttreiber verbirgt sich noch eine ActiveX Bibliothek, da habe ich keinen Einfluss drauf. Kurz gesagt, beim Starten eines Programms, wird noch eben die Funktion RunProgramFunction() als Parameter mitgegeben, sodass es bekannt ist, welche Funktion bei einer Statusänderung auszuführen ist.

Wenn ich dort versuche client.Send() zu verwenden, wird die Stelle sofort unterstrichen mit der Info: The name 'client' does not exist in the current context

danke!

16.807 Beiträge seit 2008
vor 5 Jahren

Wenn ich dort versuche client.Send() zu verwenden, wird die Stelle sofort unterstrichen mit der Info: The name 'client' does not exist in the current context

Natürlich brauchst Du an entsprechender Stelle das Client-Objekt. =)

Aber was wir Dir nicht abnehmen werden und halt auch nicht können ist, dass Du Dir ein paar Grundlagen aneignest.
Wir helfen hier bei konkreten Problemen: Hilfe zur Selbsthilfe; sind aber keine Lehrer, die Dir den Syntax beibringen 😉