2013-04-03 82 views
0

我試圖在多線程應用程序中使用Socket.Select,我不想使用async socket,所以這裏是我的代碼: -套接字會從隊列延遲一段時間後

public class Server { 
     private TcpListener m_listener; 
     private IConnectionFactory m_factory; 
     private List<Socket> Sockets = new List<Socket>(); 
     private ConcurrentDictionary<Socket, Connection> Clients = new ConcurrentDictionary<Socket, Connection>(); 
     private ConcurrentDictionary<string, ConcurrentQueue<Socket>> Threads = new ConcurrentDictionary<string, ConcurrentQueue<Socket>>(); 
     private int maxsockets = 0; 
     private object sync = new object(); 

     public Server(string ip, int port, IConnectionFactory factory, int maxsockets) { 
      IPAddress ipa = IPAddress.Parse(ip); 
      TcpListener listener = new TcpListener(ipa, port); 
      this.maxsockets = maxsockets; 
      m_listener = listener; 
      m_factory = factory; 

      int threads = maxsockets <= 100 ? 1 : maxsockets/100; 
      for (int i = 0; i < threads; i++) { 
       Thread th = new Thread(HandelSockets); 
       th.Name = i.ToString(); 
       Threads.TryAdd(i.ToString(), new ConcurrentQueue<Socket>()); 
       th.Start(); 
      } 
     } 

     public void HandelSockets() { 
      ConcurrentQueue<Socket> queue = Threads[Thread.CurrentThread.Name]; 
      Connection temp; 
      Socket sock; 

      while (true) { 
       try { 
        lock (sync) { 
         while (queue.TryDequeue(out sock)) { 
          if (Clients.TryGetValue(sock, out temp)) { 
           if (!temp.Alive) { 
            Sockets.Remove(sock); 
            Clients.TryRemove(sock, out temp); 
           } else { 
            temp.Receive(); 
            Console.WriteLine("recved from thread num : " + Thread.CurrentThread.Name); 
           } 
          } 
         } 
        } 
       } catch { } 
       Thread.Sleep(1); 
      } 
     } 

     public void Run() { 
      m_listener.Start(); 
      Console.WriteLine("listen started"); 
      Sockets.Add(m_listener.Server); 

      while (true) { 
       try { 
        var temp_list = Sockets.ToList(); 
        Socket.Select(temp_list, null, null, 1000); 

        foreach (Socket socket in temp_list) { 
         if (socket == m_listener.Server) { 

          var sock = m_listener.AcceptSocket(); 
          Sockets.Add(sock); 
          Connection conn = m_factory.Create(sock); 
          Clients.TryAdd(sock, conn); 
         } else if (Clients.Count >= maxsockets) { 
          Clients[socket].OnMaxConnections(); 
          break; 
         } else { 
          if (!Threads.Values.Any(x => x.Contains(socket))) { 
           var quque = Threads.Values.Where(x => !x.Contains(socket)).OrderBy(x => x.Count).First(); 
           lock (sync) { 
            quque.Enqueue(socket); 
           } 
          } 
          break; 
         } 
        } 
       } catch { 
       } 
      } 
     } 
    } 

問題是一段時間後,連接的插座中的一個將被推遲,插座的人會停止發送或接收到的其它插槽上的一個這樣做的!或者它可能需要幾秒鐘/分鐘,直到它捲土重來的接收和發送!

我不知道爲什麼會發生!?也許我選擇一個隊列的方式? ,我希望有人能指點我什麼可以讓這種延遲發生感謝。

+2

我看來,像你做一大堆工作在一個循環中尋找插座的連接(所以爲什麼你接着說:Thread.sleep代碼(1) ')。 *可能*超載CPU足以導致接收/發送曇花一現。爲什麼管理連接隊列時,你可以簡單地用異步插座辦呢?例如你已經證明約85行代碼,而您仍然沒有做與發送/接收數據的任何東西。這些85可以用異步套接字在5左右完成。 – 2013-04-07 18:04:55

回答

0
lock (sync) { 
    while (queue.TryDequeue(out sock)) { 
     if (Clients.TryGetValue(sock, out temp)) { 
      if (!temp.Alive) { 
       Sockets.Remove(sock); 
       Clients.TryRemove(sock, out temp); 
      } else { 
       temp.Receive(); 
       Console.WriteLine("recved from thread num : " + Thread.CurrentThread.Name); 
      } 
     } 
    } 
} 

我看不到你的Connection.Receive的實現,但如果它是一個阻塞調用,即不會返回它接收到的數據,那麼該線程將舉行到鎖sync對象,它是在導致您的其他線程等待,從而導致延遲。

現在,你知道是什麼原因造成的問題,您可以進行必要的修改,但我強烈建議您使用異步方法,因爲它會表現得更好,並刪除不需要完全鎖定。

編輯:哦,我才意識到這是一個老問題

+0

日Thnx您的回覆,我會conisder你剛纔告訴我,我仍然試圖修復它壽0.0 – Abanoub 2013-05-04 08:41:32