2016-07-14 11 views
0

ich lerne Steckdosen und ich habe dieses Programm:Reusing SocketAsyncEventArgs bei SendAsync Couses Endlosschleife

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); 
     } 
    } 
} 
} 

Es soll ermöglichen Nachricht schreiben, es senden und asynchron für die Antwort warten. Leider, wenn ich die erste Nachricht sende, fällt es in die Endlosschleife des Sendens. Ich habe dieses Reusing SocketAsyncEventArgs with ReceiveAsync results in infinite loop Thema gesehen, aber es hat nicht geholfen.

Antwort

1

Ich habe diese Konstruktion nie benutzt, aber;

Die Endlosschleife des Sendens könnte sein, Sie überprüfen nie, ob die zu sendenden Bytes gesendet werden. Möglicherweise möchten Sie überprüfen, ob die BytesTransferred-Eigenschaft den zu versendenden Bytes entspricht.


Auch blockieren Sie den aktuellen Thread mit dem manuellen Reset-Ereignis .. Warum sind Sie nicht die Nicht-Asynchron Connect() mit?

+0

Bevor ich hier einige Flags verwendete: bool willRaiseEvent = sock.SendAsync (e); if (willRaiseEvent) { isSent = true; } und einchecken Zustand vor dem Senden ist es nicht gesendet, aber es funktionierte nicht so gut ConnectAsync funktioniert auch, ich habe kein Problem dort. Wie und warum sollte ich das manuelle Reset-Ereignis verwenden? Warum würde SendAsync nicht gleich nach dem Senden anhalten? –

+1

Weil Sie 'SendAsync (e);' erneut aufrufen, wenn 'ConnectSocketEventArgCompleted' aufgerufen wird. also kommst du in eine Schleife. Ich würde einen anderen Ansatz verwenden. Verwenden Sie das blockierte Connect/Send und verwenden Sie nur async für den Empfang. Macht es viel einfacher. –

+0

Wird versuchen, vielen Dank! –