2012-04-17 10 views
2

他のスレッドで同期して実行すると、アプリケーションが非同期に文字列を取得しているのでしょうか?私は別のスレッドで同期的に実行すると、合計で非同期になりますか?

私は実際にBeginSend/BeginReceiveの使い方を知らないので、socket.Send(...)、socket.Receive(...)を別のスレッドで使用すると、アプリケーションが非同期接続をシミュレートします。

ところで、文字列がバッファのサイズよりも大きければどうなりますか?私はtelnetを使用していましたが、telnetは実際にはキーボードから取得した文字列を実際に送信します。実際にはバッファのサイズを超えることはできませんが、フルストリングを送信する別のクライアントを使用した場合はどうなりますか?私はバッファを送信することができることをプログラムに伝える方法はありますか(socketReceiveの結果である私の変数recvを通して)?

コード:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 
using System.Runtime.Remoting.Messaging; 

namespace CSharp_Console_Application 
{ 
    class Program 
    { 
     delegate Socket GetClients(); 
     static GetClients newClients; 
     static List<Socket> clients; 

     static ManualResetEvent allDone = new ManualResetEvent(false); 

     static void Main(string[] args) 
     { 
      IPEndPoint serverIPEP = new IPEndPoint(IPAddress.Any, 9080); 
      Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      serverSocket.Bind(serverIPEP); 
      serverSocket.Listen(10); 

      Console.WriteLine("Waiting for connections..."); 

      clients = new List<Socket>(); 

      newClients =() => 
       { 
        Socket clientSocket = serverSocket.Accept(); 
        IPEndPoint clientIPEP = (IPEndPoint)clientSocket.RemoteEndPoint; 

        Console.WriteLine("Connected to {0}.", clientIPEP); 

        clients.Add(clientSocket); 

        SendString("Welcome to my server!", clientSocket); 
        return clientSocket; 
       }; 

      while (true) 
      { 
       allDone.Reset(); 

       newClients.BeginInvoke((itfAR) => 
        { 
         allDone.Set(); 

         AsyncResult ar = (AsyncResult)itfAR; 
         GetClients invokedDelegate = (GetClients) ar.AsyncDelegate; 

         Socket clientSocket = invokedDelegate.EndInvoke(itfAR); 
         IPEndPoint clientIPEP = (IPEndPoint)clientSocket.RemoteEndPoint; 

         Console.WriteLine("Sent 'Welcome!' to {0}.", clientIPEP); 

         string currentString = ""; 
         while (true) 
         { 
          currentString += ReceiveString(clientSocket); 
          if (currentString.Contains('\n')) 
          { 
           Console.Write(clientIPEP + " said: " + currentString); 

           List<Socket> clientsWithoutThis = new List<Socket>(); 
           clientsWithoutThis.AddRange(clients); 
           clientsWithoutThis.Remove(clientSocket); 
           SendToAll(clientsWithoutThis, currentString); 

           currentString = ""; 
          } 
         } 
        }, 
        null); 

       allDone.WaitOne(); 
      } 
     } 

     static void SendToAll(List<Socket> clients, string message) 
     { 
      byte[] data = new byte[1024]; 
      clients.ForEach(clientSocket => 
       { 
        IPEndPoint clientIPEP = (IPEndPoint)clientSocket.RemoteEndPoint; 
        data = Encoding.ASCII.GetBytes(clientIPEP + " said: " + message + "\r"); 
        clientSocket.Send(data, data.Length, SocketFlags.None); 
       }); 
     } 

     static void SendString(string message, Socket clientSocket) 
     { 
      byte[] data = new byte[1024]; 
      data = Encoding.ASCII.GetBytes(message + "\n\r"); 
      clientSocket.Send(data, data.Length, SocketFlags.None); 
     } 

     static string ReceiveString(Socket clientSocket) 
     { 
      byte[] data = new byte[1024]; 
      int recv = clientSocket.Receive(data, data.Length, SocketFlags.None); 

      if (recv < 1) 
       return null; 

      string receivedString = Encoding.ASCII.GetString(data, 0, recv); 
      return receivedString; 
     } 
    } 
} 
+0

なぜ非同期メソッドを使用しないのか、非同期に送受信する必要があるのですか? –

+0

@ Thanatos文字列がバッファよりも大きければどうなるでしょうか?まあ、TCPは、1回の送信が1回の受信と等しいことを保証しません。それで、あなたが1であなたの完全な文字列を受け取っていないときはどうなりますか?サーバーで1回送信したときに送信したのと同じ文字列を受信するために2〜3回受信するとどうなりますか?これは、1送信がバッファサイズより大きいことと同じ状況です。 – Mausimo

答えて

0

あなたManualResetEventは無用になりがちであるこの方法です。メインスレッドをブロックするとすぐに、BeginInvokeの最初の行で、set()を呼び出して解放します。そしてもう一度それをリセットして待機状態にしますが、もう1つのBeginInvokeコールはコードのブロックを解除し、もう1つはBeginInvokeがまだ実行されている可能性があります。最終的には、複数のBeginInvokeスレッドがあり、最終的には複数の例外またはメモリ不足エラーが発生します。

関連する問題