异步UDP套接字的问题

时间:2009-05-15 13:56:50

标签: c# sockets .net-2.0 udp

我在套接字编程方面有点挣扎(我不熟悉的东西),我找不到任何有助于谷歌或MSDN(可怕)的东西。抱歉这个。

基本上我有一个现有的服务,可以通过UDP接收和响应请求。我根本无法改变这一点。

我的webapp中还有一个客户端,可以调度和侦听对该服务的响应。我给出的现有客户端是一个单例,它创建一个套接字和一个响应槽数组,然后创建一个带有无限循环方法的后台线程,使得“sock.Receive()”调用并将接收到的数据推送到插槽阵列。关于这一切的所有事情对我来说都是错误的,并且无限的线程会破坏我的单元测试,所以我试图将这个服务替换为使得它的异步发送/接收的服务。

第1点:这是正确的方法吗?我想要一种非阻塞,可扩展,线程安全的服务。

我的第一次尝试大致是这样的,哪种方式有效,但我得到的数据总是比预期的短(即缓冲区没有请求的字节数),并且似乎在处理时抛出异常。

private Socket MyPreConfiguredSocket;

public object Query()
{
    //build a request

    this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);

    IAsyncResult h = this._sock.BeginReceiveFrom(response, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), this._sock);

    if (!h.AsyncWaitHandle.WaitOne(TIMEOUT)) { throw new Exception("Timed out"); }

    //process response data (always shortened)
}

private void ARecieve (IAsyncResult result) 
{
    int bytesreceived = (result as Socket).EndReceiveFrom(result, ref this._target);
}

我的第二次尝试是基于更多谷歌拖网和我经常看到的这种递归模式,但这个版本总是超时! 从未到达ARecieve。

public object Query()
{
    //build a request

    this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);

    State s = new State(this.MyPreConfiguredSocket);

    this.MyPreConfiguredSocket.BeginReceiveFrom(s.Buffer, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);

    if (!s.Flag.WaitOne(10000)) { throw new Exception("Timed out"); } //always thrown

    //process response data
}

private void ARecieve (IAsyncResult result) 
{
    //never gets here!
    State s = (result as State);
    int bytesreceived = s.Sock.EndReceiveFrom(result, ref this._target);

    if (bytesreceived > 0)
    {
        s.Received += bytesreceived;

        this._sock.BeginReceiveFrom(s.Buffer, s.Received, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
    }
    else
    {
        s.Flag.Set();
    }
}

private class State
{
    public State(Socket sock)
    {
        this._sock = sock;
        this._buffer = new byte[BUFFER_SIZE];
        this._buffer.Initialize();
    }

    public Socket Sock;    
    public byte[] Buffer;    
    public ManualResetEvent Flag = new ManualResetEvent(false);  
    public int Received = 0;
}
第2点:很明显我得到了一些非常错误的东西。

第3点:我不确定我是否正确行事。来自远程服务的数据如何进入正确的监听线程?我是否需要为每个请求创建一个套接字?

离开我的舒适区。需要帮助。

4 个答案:

答案 0 :(得分:0)

不是解决方案,只是一个建议 - 提出最简单的代码,剥离所有线程/事件/等。从那里开始添加所需的,仅需要的复杂性。我的经验总是在这个过程中我会发现我做错了什么。

答案 1 :(得分:0)

您的程序SUDO概述如下?

Socket MySocket;
Socket ResponceSocket;

byte[] Request;
byte[] Responce;

public byte[] GetUDPResponce()
{
    this.MySocket.Send(Request).To(ResponceSocket);

    this.MySocket.Receive(Responce).From(ResponceSocket);

    return Responce;
}
生病了! 第二个代码是我们可以使用的代码和前进的方式。

但你是对的!文件不是最好的。

答案 2 :(得分:0)

您确定知道您收到了对您发送的邮件的回复吗?从套接字中删除异步行为,并尝试同步发送和接收(即使这可能会阻止您的线程)。一旦您知道此行为正常,请编辑您的问题并发布该代码,我将帮助您使用线程模型。一旦网络部分(即发送/接收)正在工作,线程模型就非常简单。

答案 3 :(得分:0)

一个可能的问题是,如果您的发送操作进入服务器,并且它在Windows设置异步侦听器之前响应。如果你没有听,那么你不会接受这些数据(与TCP不同) 尝试在发送操作之前调用beginread。