C#TCP服务器等待2个客户端响应

C#TCP服务器等待2个客户端响应,c#,multithreading,tcp,client,server,C#,Multithreading,Tcp,Client,Server,我目前正在做一个服务器/客户端项目。 我的问题是,服务器如何等待两个特定连接的响应 服务器: private TcpListener tcpListener; private Thread listenThread; private List<Connection> ConList = new List<Connection>(); Queue queue = new Queue(); public struct Connection { public Str

我目前正在做一个服务器/客户端项目。 我的问题是,服务器如何等待两个特定连接的响应

服务器:

private TcpListener tcpListener;
private Thread listenThread;
private List<Connection> ConList = new List<Connection>();
Queue queue = new Queue();

public struct Connection
{
     public Stream stream;
     public StreamWriter streamw;
     public StreamReader streamr;
     public TcpClient tcpC;
}


private void ListenForClients()
{
     this.tcpListener.Start();

     while (true)
     {
         try
         {
            Connection c = new Connection();
            c.tcpC = this.tcpListener.AcceptTcpClient();

            c.stream = c.tcpC.GetStream();
            c.streamr = new StreamReader(c.stream);
            c.streamw = new StreamWriter(c.stream);

            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));

            clientThread.Start(c);

            queue.Enqueue(c);
         }
         catch()
         {
             break;
         }
     }
 }
 private void HandleClientComm(Object client)
 {
     Connection con;
     con = (Connection)client;

     ConList.Add(con);

     byte[] message = new byte[4096];
     int bytesRead;

     while (true)
     {
         bytesRead = 0;

         try
         {

                bytesRead = con.stream.Read(message, 0, 4096);

                string s = Encoding.UTF8.GetString(message, 0, message.Length);
         }
         catch
         {
             //Socket error
             break;
         }

         if (bytesRead == 0)
         {
             //Client lost connection

             con.stream.Close();
             con.tcpC.Close();
             ConList.Remove(con);
             con = null;

             break;
         }
     }
 }

 private void QueueTimer_Tick(object sender, EventArgs e)
 {
      if (queue.count >= 2)
      { 
            Connection c1;
            Connection c2;

            c1 = new Connection();
            c1 = (Connection)queue.Dequeue();

            c2 = new Connection();
            c2 = (Connection)queue.Dequeue();

            //Start thread which waits for a response from both connections
      }
 }
私有TcpListener TcpListener;
私有线程listenThread;
私有列表ConList=新列表();
队列=新队列();
公共结构连接
{
公共溪流;
公共河流;
公共图书馆;
公共tcpC客户端tcpC;
}
私有void listenforcients()
{
这个.tcpListener.Start();
while(true)
{
尝试
{
连接c=新连接();
c、 tcpC=this.tcpListener.AcceptTcpClient();
c、 stream=c.tcpC.GetStream();
c、 streamr=新的StreamReader(c.stream);
c、 streamw=新的StreamWriter(c.stream);
Thread clientThread=新线程(新的参数化ThreadStart(HandleClientCommand));
clientThread.Start(c);
排队。排队(c);
}
捕获()
{
打破
}
}
}
私有void HandleClientCommand(对象客户端)
{
连接con;
con=(连接)客户端;
ConList.Add(con);
字节[]消息=新字节[4096];
int字节读取;
while(true)
{
字节读取=0;
尝试
{
bytesRead=con.stream.Read(消息,04096);
string s=Encoding.UTF8.GetString(message,0,message.Length);
}
接住
{
//套接字错误
打破
}
如果(字节读==0)
{
//客户端失去连接
con.stream.Close();
con.tcpC.Close();
ConList.Remove(con);
con=null;
打破
}
}
}
private void QueueTimer_Tick(对象发送方,事件参数e)
{
如果(queue.count>=2)
{ 
连接c1;
连接c2;
c1=新连接();
c1=(连接)queue.Dequeue();
c2=新连接();
c2=(连接)queue.Dequeue();
//启动等待两个连接响应的线程
}
}

每个连接都被放置在队列中,如果queue.count>=2(计时器每20秒检查一次),则应启动一个新线程,该线程将等待来自两个客户端的10秒超时响应。我花了三天时间想办法解决问题,但找不到好办法。你们有什么建议吗?

这里是一个简单的基于TPL的侦听器/响应器,无需专门为该过程编写线程

    private TcpListener _listener;

    public void OnStart(CommandLineParser commandLine)
    {
        _listener = new TcpListener(IPAddress.Any, commandLine.Port);
        _listener.Start();
        Task.Run((Func<Task>) Listen);
    }

    private async Task Listen()
    {
        IMessageHandler handler = MessageHandler.Instance;

        while (true)
        {
            var client = await _listener.AcceptTcpClientAsync().ConfigureAwait(false);

            // Without the await here, the thread will run free
            var task = ProcessMessage(client);
        }
    }

    public void OnStop()
    {
        _listener.Stop();
    }

    public async Task ProcessMessage(TcpClient client)
    {
        try
        {
            using (var stream = client.GetStream())
            {
                var message = await SimpleMessage.DecodeAsync(stream);
                _handler.MessageReceived(message);
            }
        }
        catch (Exception e)
        {
            _handler.MessageError(e);
        }
        finally
        {
            (client as IDisposable).Dispose();
        }
    }
}
专用TcpListener\u侦听器;
public void OnStart(CommandLineParser commandLine)
{
_侦听器=新的TcpListener(IPAddress.Any、commandLine.Port);
_listener.Start();
Task.Run((Func)Listen);
}
专用异步任务侦听()
{
IMessageHandler=MessageHandler.Instance;
while(true)
{
var client=await\u listener.AcceptTcpClientAsync().ConfigureAwait(false);
//如果没有此处的等待,线程将自由运行
var task=ProcessMessage(客户端);
}
}
公共void OnStop()
{
_listener.Stop();
}
公共异步任务ProcessMessage(TcpClient客户端)
{
尝试
{
使用(var stream=client.GetStream())
{
var message=wait SimpleMessage.decodeAxync(流);
_handler.MessageReceived(message);
}
}
捕获(例外e)
{
_handler.MessageError(e);
}
最后
{
(客户端作为IDisposable.Dispose();
}
}
}

首先谈谈QueueTimer\u Tick()函数。其中包含以下代码:

c1 = new Connection();
c1 = (Connection)queue.Dequeue();
第一行不需要,它创建了一个新的连接对象,该对象立即被从队列中拉出的任何内容覆盖。Alos什么东西不能像使用类型化列表一样使用类型化队列

要回答你的问题,我认为你追求的是方法。它将获取套接字列表并检查它们的可读性,还允许指定超时

要实现您想要的,您需要在循环中调用Select(),每次检查尚未变得可读的客户机的可读性时,都要在循环中调用Select()。您还需要计算出每个要选择的调用使用了多少10秒延迟,并相应地调整超时

因此,在psuedo代码中:

create L1 a list of sockets that are to be readable
set the timeout T to 10 seconds
while L1 is not empty
   copy L1 to a tempory list L2
   Socket.Select(L2,T)
   If a timeout then exit loop
   Remove the socket(s) that are readable from L1
   recalculate T based on how long the Select took
End While
注意:TcpClient.Client()方法获取TcpClient的套接字