0

我在套接字编程方面有点挣扎(我一点也不熟悉),我找不到任何可以从谷歌或 MSDN 中得到帮助的东西(糟糕)。为这篇文章的长度道歉。

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

我的 web 应用程序中还有一个客户端,它调度和侦听对该服务的响应。我得到的现有客户端是一个单例,它创建一个套接字和一个响应槽数组,然后使用无限循环方法创建一个后台线程,该方法进行“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

4 回答 4

0

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

于 2009-05-15T14:23:00.313 回答
0

您确定您会收到对您发送的消息的回复吗?从套接字中删除异步行为,并尝试同步发送和接收(即使这可能暂时阻塞您的线程)。一旦您知道此行为有效,请编辑您的问题并发布该代码,我将帮助您处理线程模型。一旦网络部分,即发送/接收,工作,线程模型是相当简单的。

于 2009-05-15T15:38:31.757 回答
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;
}

生病尝试帮助!第二个代码帖子是我们可以使用的代码和前进的方向。

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

于 2009-05-15T15:28:29.970 回答
0

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

于 2010-04-07T23:37:07.810 回答