【问题标题】:Reusing SocketAsyncEventArgs at sendAsync couses infinite loop在 sendAsync 处重用 SocketAsyncEventArgs 会导致无限循环
【发布时间】:2016-07-14 22:52:22
【问题描述】:

我正在学习套接字并且我有这个程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace client
{
public class MyClient
{
    static ManualResetEvent _clientDonte = new ManualResetEvent(false);
    private static Socket _clientSocket;
    private SocketAsyncEventArgs _connectSocketEventArg;
    private CancellationTokenSource _cancelationTokenSource;

    public MyClient()
    {

    }

    public void Start(string address, uint port)
    {
        _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse(address), (int)port);
        _connectSocketEventArg = new SocketAsyncEventArgs();

        _connectSocketEventArg.Completed += ConnectSocketEventArgCompleted;
        _connectSocketEventArg.RemoteEndPoint = serverEP;
        _connectSocketEventArg.UserToken = _clientSocket;

        _clientSocket.ConnectAsync(_connectSocketEventArg);
        _clientDonte.WaitOne();
        Console.WriteLine("DAJESZ KURWA, NAPISZ COS!");
        while (true)
        {
            SendFromConsole();
        }

    }

    private void SendFromConsole()
    {
        var message = Console.ReadLine();
        var buff = Encoding.ASCII.GetBytes(message);
        _connectSocketEventArg.SetBuffer(buff, 0, buff.Length);
        _clientSocket.SendAsync(_connectSocketEventArg);
    }

    private void ConnectSocketEventArgCompleted(object sender, SocketAsyncEventArgs e)
    {
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Connect:
                ProcessConnect(e);
                break;
            case SocketAsyncOperation.Receive:
                ReceiveAsync(e);
                break;
            case SocketAsyncOperation.Send:
                SendAsync(e);
                break;
            default:
                throw new Exception("Invalid operation completed");
        }
    }

    private void SendAsync(SocketAsyncEventArgs e)
    {
        if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
        {
            Socket sock = e.UserToken as Socket;
            bool willRaiseEvent = sock.SendAsync(e);
            if (!willRaiseEvent)
            {
                ReceiveAsync(e);

            }
        }

    }

    private void ReceiveAsync(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {
            Console.WriteLine("SERVER>>: {0}", Encoding.ASCII.GetString(e.Buffer));
            Socket sock = e.UserToken as Socket;
        }
    }

    private void ProcessConnect(SocketAsyncEventArgs e)
    {
        _cancelationTokenSource = new CancellationTokenSource();
        Task.Factory.StartNew(ProgressConnect, _cancelationTokenSource.Token);

        if (e.SocketError == SocketError.Success)
        {
            Thread.Sleep(701);
            _cancelationTokenSource.Cancel();
            Console.WriteLine("Nawiazano polaczenie!");
            _clientDonte.Set();
        }
        else if (e.SocketError == SocketError.SocketError)
        {
            Console.WriteLine("Nie udalo sie! nacisnij cos by wyjsc");
            Console.ReadKey();
            Environment.Exit(0);
        }
    }

    private void ProgressConnect()
    {
        while (!_cancelationTokenSource.Token.IsCancellationRequested)
        {
            Console.Write(".");
            _cancelationTokenSource.Token.WaitHandle.WaitOne(700);
        }
    }
}
}

它应该允许异步写入、发送和等待响应。不幸的是,当我发送第一条消息时,它陷入了发送的无限循环。 我看过这个Reusing SocketAsyncEventArgs with ReceiveAsync results in infinite loop 主题,但没有帮助。

【问题讨论】:

    标签: c# sockets asynchronous


    【解决方案1】:

    我从未使用过这种结构,但是;

    发送的无限循环可能是,您永远不会检查您尝试发送的字节是否已发送。您可能需要检查 BytesTransferred 属性是否等于您尝试发送的字节数。


    另外,您正在使用手动重置事件阻塞当前线程。您为什么不使用非异步Connect()

    【讨论】:

    • 在我在这里使用一些标志之前:bool willRaiseEvent = sock.SendAsync(e); if (willRaiseEvent) { isSent = true;并在发送之前检查条件,它没有发送,但它不能正常工作 ConnectAsync 也能正常工作,我没有问题。我应该如何以及为什么要使用手动重置事件?为什么 SendAsync 不会在一次发送后停止?
    • 因为您在调用ConnectSocketEventArgCompleted 时再次调用SendAsync(e);。所以你进入了一个循环。我会使用不同的方法。使用被阻止的连接/发送并仅使用异步进行接收。让它更容易。
    猜你喜欢
    • 2010-11-24
    • 2011-08-23
    • 2016-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多