首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SocketAsyncEventArgs.UserToken没有更新吗?

SocketAsyncEventArgs.UserToken没有更新吗?
EN

Stack Overflow用户
提问于 2011-09-29 21:42:36
回答 1查看 1.1K关注 0票数 1

我目前有一个客户机服务器应用程序,涉及Silverlight客户端和.NET服务器。.NET部分使用System.Net.Sockets命名空间中提供的Tcp类,而Silverlight客户端使用原始套接字。我从目前使用HttpListener类的代码中移植到这里,因为它不适合我的需要。不过,Http类在SL端具有使用Begin*和End*样式异步方法的能力,这些方法允许我在操作完成后指定处理程序。我很难让这个系统和新系统一起工作。我目前的策略是将处理程序作为UserToken的一部分。但是,似乎没有更新此令牌。

这是一些修改过的代码。我可以让双方对话,但似乎正确的UserToken没有被发送。

代码语言:javascript
复制
public class ClientUserToken
{
    public Handler Handler { get; set; }
    public string Test { get; set; }

    public ClientUserToken(Handler handler, string test)
    {
        Handler = handler;
        Test = test;
    }
}

public class SocketClient
{
    private Socket _clientSocket;
    private string _ipAddress;
    private int _port;

    private void OpenSocket()
    {
        var endPoint = new DnsEndPoint(_ipAddress, _port);

        SocketAsyncEventArgs args = new SocketAsyncEventArgs();
        args.UserToken = new ClientUserToken(null, "foo");
        args.RemoteEndPoint = endPoint;
        args.Completed += OnSocketCompleted;

        _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _clientSocket.ConnectAsync(args);
    }

    void OnSocketCompleted(object sender, SocketAsyncEventArgs e)
    {
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Connect: ProcessConnect(e); break;
            case SocketAsyncOperation.Receive: ProcessReceive(e); break;
            case SocketAsyncOperation.Send: ProcessSend(e); break; // this never gets called
        }
    }

    void ProcessConnect(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {
            byte[] response = new byte[1024];
            e.SetBuffer(response, 0, response.Length);
            _clientSocket.ReceiveAsync(e);
        }
    }

    void ProcessReceive(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
        {
            var userToken = e.UserToken as ClientUserToken; // this token is always the one set in ProcessConnect

            // process the data

            if (!_clientSocket.ReceiveAsync(e))
            {
                ProcessReceive(e);
            }
        }
    }

    // this is never called, for some reason
    void ProcessSend(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {
            var userToken = e.UserToken as ClientUserToken;

            if (!_clientSocket.ReceiveAsync(e))
            {
                ProcessReceive(e);
            }
        }
    }

    // this is the public API that users use to actually send data across
    public void SendToServer(byte[] data, int len, Handler handler)
    {
        SocketAsyncEventArgs args = new SocketAsyncEventArgs();

        args.UserToken = new ClientUserToken(handler, "bar");
        args.SetBuffer(data, 0, len);

        if (!_clientSocket.SendAsync(args))
        {
            ProcessReceive(args);
        }
    }
}

正如上面的注释所示,在ProcessReceive中,userToken.Test总是"foo“,userToken.Handler总是空的。

到目前为止,我还无法进入ProcessSend,所以我无法看到它到底发送了什么SocketAsyncEventArgs。谁知道为什么这个事件没有发射(发送后完成)?我是不是搞砸了我的SendToServer函数?

我意识到同步可能还存在其他问题,但我不认为这是问题所在。我做过的一件事是设置一个ManualResetEvent,以确保在连接完成之前没有人向服务器发送数据(ProcessConnect),但这也解决不了这个问题。

任何帮助都将不胜感激!

编辑:--所以发生这种情况的原因是,当我在ProcessConnect函数中调用ReceiveAsync时,当服务器为我的数据发送响应时,就会使用它。因此,处理程序中存在UserToken "foo“。下一次服务器发送数据时,ReceiveAsync使用带有UserToken "bar“的args。所以对于双工通信位来说,这是不同步的。我无法确保我从客户端发送的SocketAsyncEventArgs与响应中使用的相同。似乎唯一的解决方案是让SL客户端打开两个套接字--一个用于服务器启动的数据,另一个用于客户端发起的请求。然而,这意味着我没有利用双重性质。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-10-05 21:41:03

这个模型不能工作,因为我正在为每个发送创建一个新的SocketAsyncEventArgs,这意味着数据可以返回到这些arg中的任何一个。我一直在走向一个有一个SocketAsyncEventArgs池的模型,每个客户机一次只能有一个请求/响应。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7603734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档