繁体   English   中英

异步UDP套接字的问题

[英]Problems with Asynchronous UDP Sockets

我在套接字编程方面有点挣扎(我一点都不熟悉),但是我找不到任何对Google或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);
}

我的第二次尝试是基于更多的Google拖网捕捞和我经常看到的这种递归模式,但是这个版本总是超时! 永远不会到达。

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点:我不确定是否要解决这个问题。 来自远程服务的数据如何到达正确的侦听线程? 我是否需要为每个请求创建一个套接字?

在我的舒适区之外。 需要帮忙。

一个可能的问题是,如果您的发送操作转到服务器,并且它在Windows设置异步侦听器之前做出响应。 如果您不收听数据,则不会接受您的数据(与TCP不同),请尝试在发送操作之前调用beginread。

不是一个适合您的解决方案,只是一个建议-提出最简单的代码,该代码可以剥离所有线程/事件/等。 从那里开始,添加所需的(也是唯一所需的)复杂性。 我的经验始终是,在此过程中,我会发现自己做错了什么。

那么您的程序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;
}

虐待尝试帮助! 第二篇代码文章是我们可以使用的代码以及前进的道路。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM