2012-04-17 60 views
2

我想知道如果我的應用程序異步獲取字符串,如果我在其他線程同步運行它?如果我在不同的線程上同步運行,它會使它每個總線的異步?

我實際上不知道如何使用BeginSend/BeginReceive,所以我在不同的線程上使用了socket.Send(...),socket.Receive(...),這樣做會使我的應用程序模擬異步連接。

順便說一句,如果字符串大於緩衝區的大小,會發生什麼情況?對於我使用telnet的客戶端,但telnet實際上是在從鍵盤獲得的時候發送字符串,所以我實際上不能超過緩衝區的大小,但是如果我使用另一個發送完整字符串的客戶端呢?有沒有辦法告訴程序,我發送更多然後緩衝區允許它(通過我的變量recv這是socketReceive的結果)?

代碼:

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

請問爲什麼你只是不使用異步方法,當你想發送和接收異步? – 2012-04-18 06:29:58

+0

@Thanatos你問如果字符串大於緩衝區會發生什麼?那麼,TCP不保證1發送等於1接收。那麼,如果在1次接收中沒有收到完整的字符串,會發生什麼?當需要2或3個接收者收到您在服務器上發送的同一個字符串時,會發生什麼情況?這與1發送大於緩衝區大小的情況相同。 – Mausimo 2013-01-10 22:10:02

回答

0

這樣你ManualResetEvent是往往是無用的。只要您阻止主線程,您就會在BeginInvoke的第一行中釋放,並撥打set()。然後,您再次重置設置爲等待狀態,但另一個BeginInvoke呼叫將解除對該代碼的阻止,而另一個BeginInvoke可能仍在運行。所以最後你會有多個BeginInvoke線程,最終你會有多個異常或內存不足錯誤。