加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

如何在多线程c#中使用TCP客户端/监听器?

发布时间:2020-12-14 19:33:10 所属栏目:Java 来源:网络整理
导读:我已经为我的服务器编写了这段代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Threading; using System.Net.Sockets; using System.IO;name
我已经为我的服务器编写了这段代码:
using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net;
    using System.Threading;
    using System.Net.Sockets;
    using System.IO;


namespace ConsoleApplication1
{
    class Program
    {
        private static bool terminate;

        public static bool Terminate
        {
            get { return terminate; }
        }

        private static int clientNumber = 0;
        private static TcpListener tcpListener;

        static void Main(string[] args)
        {
            StartServer();
            Console.Read();
        }

        private static void StartServer()
        {
            try
            {
                Console.WriteLine("Server starting...");
                tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"),8000);
                terminate = false;
                tcpListener.Start();
                tcpListener.BeginAcceptTcpClient(ConnectionHandler,null);
                Console.ReadLine();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally 
            {
                Console.WriteLine("Server stopping...");
                terminate = true;
                if (tcpListener != null)
                {
                    tcpListener.Stop();
                }
            }
        }

        private static void ConnectionHandler(IAsyncResult result)
        {
            TcpClient client = null;

            try
            {
                client = tcpListener.EndAcceptTcpClient(result);
            }
            catch (Exception)
            {
                return;
            }

            tcpListener.BeginAcceptTcpClient(ConnectionHandler,null);

            if (client!=null)
            {
                Interlocked.Increment(ref clientNumber);
                string clientName = clientNumber.ToString();
                new ClientHandler(client,clientName);
            }
        }
    }
}


   class ClientHandler
    {
        private TcpClient client;
        private string ID;

        internal ClientHandler(TcpClient client,string ID)
        {
            this.client = client;
            this.ID = ID;
            Thread thread = new Thread(ProcessConnection);
            thread.IsBackground = true;
            thread.Start();
        }

        private void ProcessConnection()
        {
            using (client)
            {
                 using (BinaryReader reader=new BinaryReader(client.GetStream()))
                 {
                     if (reader.ReadString()==Responses.RequestConnect)
                     {
                          using (BinaryWriter writer=new BinaryWriter(client.GetStream()))
                          {
                              writer.Write(Responses.AcknowledgeOK);
                              Console.WriteLine("Client: "+ID);
                              string message = string.Empty;
                              while (message!=Responses.Disconnect)
                              {
                                  try
                                  {
                                      message = reader.ReadString();
                                  }
                                  catch
                                  {
                                      continue;
                                  }
                                  if (message==Responses.RequestData)
                                  {
                                      writer.Write("Data Command Received");
                                  }
                                  else if (message==Responses.Disconnect)
                                  {
                                      Console.WriteLine("Client disconnected: "+ID);
                                  }
                                  else
                                  {
                                      Console.WriteLine("Unknown Command");
                                  }
                              }
                          }
                     }
                     else
                     {
                         Console.WriteLine("Unable to connect client: "+ID);
                     }
                 }
            }
        }
    }

   class Responses
    {
        public const string AcknowledgeOK = "OK";
        public const string AcknowledgeCancel = "Cancel";
        public const string Disconnect = "Bye";
        public const string RequestConnect = "Hello";
        public const string RequestData = "Data";
    }

此代码以多线程方式侦听客户端请求.我无法理解如何区分连接到此服务器的不同客户端以及哪个客户端正在断开连接并请求不同的命令.

我的客户代码是:

private static void clietnRequest(string message,ref string response)
{
    using (TcpClient client = new TcpClient())
    {
        if (!client.Connected)
        {
            client.Connect(IPAddress.Parse("127.0.0.1"),8000);
            using (NetworkStream networkStream = client.GetStream())
            {
                using (BinaryWriter writer = new BinaryWriter(networkStream))
                {
                    writer.Write(Responses.RequestConnect);
                    using (BinaryReader reader = new BinaryReader(networkStream))
                    {
                        if (reader.ReadString() == Responses.AcknowledgeOK)
                        {
                            response = Responses.AcknowledgeOK;

                        }
                    }
                }
            }
        }
    }
}

这段代码将客户端连接到服务器,但我无法再发送消息.我想在我的应用程序中,如果客户端已连接,那么他可以向服务器发送命令.而不是这样做它每次充当服务器的新客户端.我在这里遗漏了一些东西,请指引我正确的方向.我对c#网络编程完全不熟悉.请帮助我改进我的代码. Tcp Listener和Tcp Client对此方案有效还是需要使用套接字?

解决方法

您在发送消息后每次客户端关闭连接,如果您想这样做没有任何问题,但您需要向服务器发送某种形式的标识,以便它可以告诉您这不是新的连接,但旧连接第二次连接.这正是HTTP协议正在做的事情,“识别”是互联网cookie.

如果您不经常传输数据,那么第一个选项就可以了,但如果您经常这样做,则需要保持连接打开.

基本上,您需要采取连接和断开客户端请求函数的行为,并将打开的连接作为参数传递.

private void MainCode()
{
    using (TcpClient client = new TcpClient())
    {
        client.Connect(IPAddress.Parse("127.0.0.1"),8000);

        while(variableThatRepresentsRunning)
        {
            //(Snip logic that gererates the message)

            clietnRequest(message,ref response,client);

            //(Snip more logic)
        }
    }
}

private static void clietnRequest(string message,ref string response,TcpClient client)
{
    if (client.Connected)
    {
        using (NetworkStream networkStream = client.GetStream())
        {
            using (BinaryWriter writer = new BinaryWriter(networkStream))
            {
                writer.Write(Responses.RequestConnect);
                using (BinaryReader reader = new BinaryReader(networkStream))
                {
                    if (reader.ReadString() == Responses.AcknowledgeOK)
                    {
                        response = Responses.AcknowledgeOK;

                    }
                }
            }
        }
    }
    else
    {
        //Show some error because the client was not connected
    }
}

通过这种方式,客户端对象服务器端代表客户端,每个连接的客户端将有一个它的实例,并将保持与该客户端的关联,直到他断开连接.如果要跟踪所有连接的客户端,则需要将它们全部插入到某个集合中,例如List< TcpClient> (要么使用Concurrent Collection,要么使用锁定,因为您是多线程的)然后您将拥有所有客户端的列表(您需要让客户端自行清理,以便在断开连接后将其自己从列表中删除).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读