2016-07-14 12 views
0

をcouses私はソケットを学んだし、私はこのプログラムを持っている:メッセージを書き、それを送信し、非同期応答を待つことができるようになっている再利用SocketAsyncEventArgsが無限ループに

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トピックを見ましたが、それは助けになりませんでした。

答えて

1

この構造は一度も使用しませんでしたが、

送信の無限ループは、送信しようとしているバイトが送信されているかどうかを決して確認できないことがあります。 BytesTransferredプロパティが送信しようとしているバイト数と等しいかどうかを確認したい場合があります。


はまた、あなたはなぜあなたは非非同期Connect()を使用していない...手動リセットイベントを、現在のスレッドをブロックしていますか?

+0

私はここでいくつかのフラグを使用していました: bool willRaiseEvent = sock.SendAsync(e); if(willRaiseEvent) { isSent = true; } 送信前に状態が送信されていませんが、正常に動作していません。 ConnectAsyncも動作していますが、問題はありません。 手動リセットイベントを使用する方法とその理由を教えてください。 SendAsyncが1回送信した直後に停止しないのはなぜですか? –

+1

あなたは 'ConnectSocketEventArgCompleted'が呼び出されたときに' SendAsync(e); 'をもう一度呼び出すためです。あなたはループに入っています。私は別のアプローチを使用します。ブロックされたConnect/Sendを使用し、受信にasyncを使用するだけです。それはずっと楽になります。 –

+0

試してみるよ、ありがとう! –