尝试创建可以写入Console或Form应用程序的方法

时间:2011-05-31 15:34:12

标签: c# client client-server

我正在开发一般服务器和客户端程序。我面临的问题是当我在我的客户端和服务器中的OnDataReceived时,我不知道如何处理数据。理想情况下,它应该将接收的数据输出到窗口中,但我不知道它是否是Form或Console应用程序。所以问题是如何创建一个可以处理两者的通用方法,或者如果不可能,我应该做什么呢?

我正在使用的代码:

            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;
     }
    }

PS。 我不知道是否需要知道,但我正在做异步客户端/服务器。

5 个答案:

答案 0 :(得分:3)

您的沟通课程不应该关心他们收到的数据会发生什么。相反,他们应该将数据提供给想要它的类。一种方法是提供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);
        }
    }
}

在你的听众课程中:

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);
    }
}

答案 1 :(得分:2)

使用字符串触发事件?如果数据缓冲区字符串是套接字对象的成员,我会帮助你 - 然后你可以只使用套接字对象&你的事件处理程序,无论结果如何,都将拥有决定如何处理数据所需的一切。

RGDS, 马丁

答案 2 :(得分:1)

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

答案 3 :(得分:1)

您可以尝试实施策略

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);

希望有所帮助

答案 4 :(得分:0)

这是依赖注入的好位置。

  1. 创建一个接口(我们现在称之为ISiemsen),它有一个名为“ShowTheResult”的字符串属性
  2. 现在,您希望能够显示结果的任何对象(表单,控制台应用程序,Web表单......),您实现了ISiemsen界面
  3. 在为“ShowTheResult”设置的属性中,您可以将值分配给该对象所需的任何填充。 (如果是控制台,则执行console.WriteLine(value),如果是表单,则将值分配给文本框)
  4. 将您的工作流程更改为接受对您的工作人员功能的引用,并让它在需要的地方发送响应。

    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);
     }
    
  5. 使用这种技术,UI元素不知道或关心数据来自何处,而工作者进程不知道或关心去哪里......它是“松散耦合”。