Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/430.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 尝试创建一个可以写入控制台或窗体应用程序的方法_C#_Client_Client Server - Fatal编程技术网

C# 尝试创建一个可以写入控制台或窗体应用程序的方法

C# 尝试创建一个可以写入控制台或窗体应用程序的方法,c#,client,client-server,C#,Client,Client Server,我在一个通用服务器和一个客户端程序上工作。我面临的问题是,当我在客户端和服务器的OnDataReceived中时,我不知道如何处理数据。理想情况下,它应该将接收到的数据输出到一个窗口中,但我不知道它是表单应用程序还是控制台应用程序。所以问题是我如何创建一个可以同时处理这两个问题的通用方法,或者如果不可能,我应该怎么做 我正在使用的代码: SocketPacket theSockId = (SocketPacket)asyn.AsyncState;

我在一个通用服务器和一个客户端程序上工作。我面临的问题是,当我在客户端和服务器的OnDataReceived中时,我不知道如何处理数据。理想情况下,它应该将接收到的数据输出到一个窗口中,但我不知道它是表单应用程序还是控制台应用程序。所以问题是我如何创建一个可以同时处理这两个问题的通用方法,或者如果不可能,我应该怎么做

我正在使用的代码:

            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;

            int iRx = theSockId.m_currentSocket.EndReceive(asyn);
            char[] chars = new char[iRx + 1];
            Decoder decode = Encoding.Default.GetDecoder();
            int charLength = decode.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
            String szData = new String(chars);

            //Handle Message here

            WaitForData();
和套接字包类:

    class SocketPacket
    {
     public Socket m_currentSocket;
     public byte[] dataBuffer = new byte[1024];//Buffer to store the data by the client

     public SocketPacket(Socket socket)
     {
        m_currentSocket = socket;
     }
    }
附言。
我不知道是否需要知道,但我正在做异步客户机/服务器。

我将创建一个接口,可以在其中写入事件信息,比如IEventink。因此OnDataReceived与IEventSink实例一起工作,并对其调用Write方法。
然后我将有两个接口实现:一个在控制台上写,另一个在表单上写。

您的通信类不应该关心它们接收的数据发生了什么。相反,它们应该使数据可供需要它的类使用。一种方法是提供一个getData()方法,该方法接收数据,然后将其返回给调用方。更好的做法是提供DataArrived事件,该事件在您收到数据时触发。这样,任何数量的使用者都可以监听数据,但您的通信代码不必知道哪些类正在监听数据,也不必知道它们打算对数据做什么

编辑

一个简单的例子:

public class MyClassWithEvent
{
    public delegate void DataArrivedDelegate(string data);
    public event DataArrivedDelegate DataArrived;

    public void GetSomeData()
    {
        // Communication code goes here; stringData has the data

        DataArrivedDelegate handler = DataArrived;
        if (handler != null)
        {
            // If you want to raise the event on this thread, this is fine
            handler(stringData);
        }
    }
}
在listener类中:

public MyListener
{

    public MyListener(MyServer server)
    {
        // Sets MyListenerMethod to be called when DataArrived is raised
        server.DataArrived += MyListenerMethod;
    }

    public void MyListenerMethod(string data)
    {
        // Do something with the data
        Console.WriteLine(data);
    }
}

你可以尝试实施战略

interface IOutputStrategy
{
    void Output(string message);
}

class ConsoleOutput:IOutputStrategy
{
    public void Output(string message)
    {
        Console.Writeline(message);
    }
}

class FormOutput:IOutputStrategy
{
    public void Output(string message)
    {
        // output where you want
    }
}
在服务器/客户端上,您将提供类型为
IOutputStrategy

//Server
IOutputStrategy instance = new ConsoleOutput();

//Client
IOutputStrategy instance = new FormOutput();
然后在OnDataReceived回调中,您可以使用当前的IOutputStrategy实例来输出消息

instance.Output(szData);

希望它有助于用字符串触发事件?如果数据缓冲区字符串是套接字对象的一个成员,我会提供帮助-然后您可以仅使用套接字对象触发事件&您的事件处理程序(不管结果如何)将拥有决定如何处理数据所需的一切

Rgds,
Martin

这是一个很好的依赖注入位置

  • 创建一个接口(我们现在称之为ISiemsen),该接口具有名为“ShowTheResult”的字符串属性
  • 现在,在任何您希望能够显示结果的对象(表单、控制台应用程序、web表单…)中,您都可以实现ISiemsen接口
  • 在“ShowTheResult”的属性集中,可以将值指定给满足该对象需要的任何对象。(如果是控制台,则执行console.WriteLine(值),如果是表单,则将值分配给文本框)
  • 将工作进程更改为接受对工作函数的引用,并让它在需要的地方发送响应

    protected void getResults(ISiemsen siemens ... ) 
     {
       SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
       int iRx = theSockId.m_currentSocket.EndReceive(asyn);
       char[] chars = new char[iRx + 1];
       Decoder decode = Encoding.Default.GetDecoder();
       int charLength = decode.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
       String szData = new String(chars);
    
    
       WaitForData();
    //Handle Message here
       siemsen.ShowTheResult(theResult);
     }
    

  • 使用这种技术,UI元素不知道或不关心数据从何而来,工作进程也不知道或不关心数据从何而来。。。它是“松散耦合”的。

    您是要创建一个程序来执行特定的功能,还是要创建一个可重用的库?不确定“通用服务器和客户端程序”是什么意思。您可以看看MVP模式。演示者将只使用视图的方法来显示数据,视图将考虑是否在控制台、窗体或html标签中显示。好的,我应该包括SocketPacket类(我现在有)它确实有DataBuffer。但是,您能否给出一个事件处理程序的外观示例,以及我如何创建事件。据我所知,我从未使用过它们。好吧,我不确定我将如何创建这样的活动。不要认为我使用过(自定义)事件,所以任何(模拟)示例都会很好。我不太确定这是如何工作的,也就是说,这会是我的客户机和服务器类的一部分吗?如果是这样,OnDataReceived会调用GetSomeData吗?可能是我完全误解了这一点。上面的类可能是客户机类和服务器类中的一个(或两个)。您只需像平常一样处理通信代码,然后在接收数据时引发事件(如上所示),以便侦听器可以对数据进行处理。我将更新示例以显示侦听器。好的,如果我理解正确的话。我只是使用szData而不是stringData。那么MyListener是使用我的服务器/客户机的任何程序(无论是窗体还是控制台应用程序)的一部分,并且将在代理中放置新数据时触发?另外,void方法MyListener应该是MyListenerMethod还是?是的,它应该是MyListenerMethod。这是基本思想,是的:允许其他类侦听数据,并让客户机/服务器告诉他们数据何时到达。