簡體   English   中英

C#TCP服務器等待2個客戶端響應

[英]C# TCP server wait for 2 clients to respond

我目前正在處理服務器/客戶端項目。 我的問題是,服務器如何等待兩個特定的連接響應?

服務器:

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
      }
 }

每個連接都放入隊列,並且如果queue.count> = 2(計時器每20秒檢查一次),則應該啟動一個新線程,該線程等待兩個客戶端的響應都以10秒超時。 我嘗試了3天,但找不到一種好的方法。 你們有什么建議嗎?

這是一個簡單的基於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();
        }
    }
}

首先要介紹您的QueueTimer_Tick()函數。 其中包含以下代碼:

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

不需要此行的第一行,它會創建一個新的Connection對象,該對象將立即被您退出隊列的所有對象覆蓋。 還不能像使用類型列表一樣使用類型隊列嗎?

要回答您的問題,我想您需要使用的是Socket.Select()方法。 它將獲取套接字列表並檢查它們的可讀性,並且還允許指定超時。

為了實現所需的功能,您需要循環調用Select(),在該循環中,每次檢查尚未可讀的客戶端的可讀性時。 您還需要確定每次選擇的呼叫在10秒延遲中使用了多少,並相應地調整超時。

所以在偽代碼中:

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的套接字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM