5

我为我的服务器编写了这段代码:

    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 对这种情况有效还是我需要使用 Sockets?

4

1 回答 1

3

每次发送消息后,您都会在客户端关闭连接,如果您想这样做没有任何问题,但您需要向服务器发送某种形式的标识,以便它可以判断这不是新的连接,但旧连接第二次连接。这正是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
    }
}

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

于 2013-01-10T06:58:32.843 回答