2016-12-14 59 views
2

我有下面的C#代码:C#SOCKET多线程拉姆达

using System.Collections.Generic; 
 
using System.Net; 
 
using System.Net.Sockets; 
 
using System.Threading; 
 

 
namespace CTCServer 
 
{ 
 
    class Server 
 
    { 
 
     //Stores the IP Adress the server listens on 
 
     private IPAddress ip; 
 

 
     //Stores the port the server listens on 
 
     private int port; 
 

 
     //Stores the counter of connected clients. *Note* The counter only gets increased, it acts as "id" 
 
     private int clientCount = 0; 
 

 
     //Defines if the server is running. When chaning to false the server will stop and disconnect all clients. 
 
     private bool running = true; 
 

 
     //Stores all connected clients. 
 
     public List<Client> clients = new List<Client>(); 
 

 
     //Event to pass recived data to the main class 
 
     public delegate void GotDataFromCTCHandler(object sender, string msg); 
 
     public event GotDataFromCTCHandler GotDataFromCTC; 
 

 
     //Constructor for Server. If autoStart is true, the server will automaticly start listening. 
 
     public Server(IPAddress ip, int port, bool autoStart = false) 
 
     { 
 
      this.ip = ip; 
 
      this.port = port; 
 

 
      if (autoStart) 
 
       this.Run(); 
 
     } 
 

 
     //Starts the server. 
 
     public void Run() 
 
     { 
 
      //Run in new thread. Otherwise the whole application would be blocked 
 
      new Thread(() => 
 
      { 
 
       //Init TcpListener 
 
       TcpListener listener = new TcpListener(this.ip, this.port); 
 

 
       //Start listener 
 
       listener.Start(); 
 

 
       //While the server should run 
 
       while (running) 
 
       { 
 
        //Check if someone wants to connect 
 
        if (listener.Pending()) 
 
        { 
 
         //Client connection incoming. Accept, setup data incoming event and add to client list 
 
         Client client = new Client(listener.AcceptTcpClient(), this.clientCount); 
 

 
         //Declare event 
 
         client.internalGotDataFromCTC += GotDataFromClient; 
 

 
         //Add to list 
 
         clients.Add(client); 
 

 
         //Increase client count 
 
         this.clientCount++; 
 
        } 
 
        else 
 
        { 
 
         //No new connections. Sleep a little to prevent CPU from going to 100% 
 
         Thread.Sleep(100); 
 
        } 
 
       } 
 

 
       //When we land here running were set to false or another problem occured. Stop server and disconnect all. 
 
       Stop(); 
 
      }).Start(); //Start thread. Lambda \(o.o)/ 
 
     } 
 

 
     //Fires event for the user 
 
     private void GotDataFromClient(object sender, string data) 
 
     { 
 
      //Data gets passed to parent class 
 
      GotDataFromCTC(sender, data); 
 
     } 
 

 
     //Send string "data" to all clients in list "clients" 
 
     public void SendToAll(string data) 
 
     { 
 
      //Call send method on every client. Lambda \(o.o)/ 
 
      this.clients.ForEach(client => client.Send(data)); 
 
     } 
 

 
     //Stop server 
 
     public void Stop() 
 
     { 
 
      //Exit listening loop 
 
      this.running = false; 
 

 
      //Disconnect every client in list "client". Lambda \(o.o)/ 
 
      this.clients.ForEach(client => client.Close()); 
 

 
      //Clear clients. 
 
      this.clients.Clear(); 
 
     } 
 
    } 
 
}

  • 应该运行不是在一个循环中创建新的线程?
  • 如果第一个问题不是真的,并且lambda表达式已经创建了新的线程,那么在哪个时候创建​​了新的线程?决定它的逻辑在哪里?

谢谢先进。

回答

3

new Thread(将创建新的线程。 lambda在线程上执行。运行应而不是处于循环中。因为它会创建很多线程。

and the lambda expression already creates new thread,no它将被用作线程方法。


唯一的问题是,你没有对线程的引用,所以你不能等到它终止。

另外,您正在使用bool running作为while循环。你最好使用ManualResetEvent


我用这个作为标准的线程设置:

// signal for terminating the thread. 
private ManualResetEvent _terminating = new ManualResetEvent(false); 
private Thread _thread; 

public void Start() 
{ 
    ManualResetEvent threadStarted = new ManualResetEvent(false); 

    _thread = new Thread(() => 
    { 
     threadStarted.Set(); 

     while(!_terminating.WaitOne(0)) 
     { 
      // do your thing here. 
     } 
    }); 

    _thread.Start(); 
    threadStarted.WaitOne(); 
} 

public void Dispose() 
{ 
    _terminating.Set(); 
    _thread.Join(); 
} 
这里

一个备注是:如果你使用线程客户端或异步插座。

  • 线程客户端:客户端数量< = 10
  • 异步套接字:客户端计数> 10

与服务器的问题是,你不负责的许多客户是如何连接的。


一些伪代码如何设置你的tcp服务器并为每个客户端运行线程。

public class Server 
{ 

    // signal for terminating the thread. 
    private ManualResetEvent _terminating = new ManualResetEvent(false); 

    private List<ClientHandler> _clients = new List<ClientHandler>(); 

    public void Start() 
    { 
     ManualResetEvent threadStarted = new ManualResetEvent(false); 

     _thread = new Thread(() => 
     { 
      threadStarted.Set(); 

      // create listener..... 

      while(!_terminating.WaitOne(0)) 
      { 
       // do your thing here. 

       // accept socket 
       var socket = _listenerSocket.Accept(); 

       ClientHandler handler = new ClientHandler(socket); 
       _clients.Add(handler); 

      } 
     }); 

     _thread.Start(); 
     threadStarted.WaitOne(); 
    } 

    public void Dispose() 
    { 
     _terminating.Set(); 
     _thread.Join(); 
    } 

} 


public class ClientHandler 
{ 
    // signal for terminating the thread. 
    private ManualResetEvent _terminating = new ManualResetEvent(false); 

    public ClientHandler(Socket socket) 
    { 
     ManualResetEvent threadStarted = new ManualResetEvent(false); 

     _thread = new Thread(() => 
     { 
      threadStarted.Set(); 

      while(!_terminating.WaitOne(0)) 
      { 
       // do your thing here. 

       // accept socket 
       var bytesReaded = socket.Read(.....); 
       // handle data.... 
      } 
     }); 

     _thread.Start(); 
     threadStarted.WaitOne(); 
    } 

    public void Dispose() 
    { 
     _terminating.Set(); 
     _thread.Join(); 
    } 
} 
+0

感谢您的回答。问题是,对于每个新的套接字连接都有一个新的线程是正确的?这段代码只创建一个线程,所以这个服务器不是多线程的?每个新连接都应该有一个线程? – redigaffi

+0

是的,您应该为每个连接的套接字创建一个新线程或**使用异步套接字**。每个套接字的线程速度更快(约1.5倍),但不具有可伸缩性。它会消耗每个客户端的线程。 –

+0

然后,我的代码片段只会创建1个线程吗?所以它不是一个多线程套接字服务器,不能接受多个连接权限?我怎么能改变它,所以它接受多个连接 – redigaffi