如何在多线程C#中使用TCP客户端/侦听器? [英] How to use TCP client/listener in multithreaded c#?

查看:105
本文介绍了如何在多线程C#中使用TCP客户端/侦听器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为服务器编写了以下代码:

I have written this code for my server:

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

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

this code listen for client requests in a multi threaded way. I am unable to understand how can i distinguish between different clients connected to my this server and which client is disconnecting and requesting for different commands.

我的客户代码是:

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侦听器和Tcp客户端在这种情况下有效,还是需要使用套接字?

this piece of code connects the client to server, but i am unable to send anymore messages. I want in my app if client is connected then he can send commands to server. instead of doing this it every time act as a new client to server. I am missing some thing here, Kindly guide me in right direction. I am totally new to c# networking programming. Kindly help me improve my code. Tcp Listener and Tcp Client is valid for this scenario or do I need to use Sockets?

推荐答案

发送消息后,每次客户端都要关闭连接,如果要这样做,那没关系,但是您需要发送对服务器的某种形式的标识,因此它可以分辨出这不是新连接,而是旧连接第二次连接.正是HTTP协议正在执行的操作,而标识"就是Internet Cookie.

You are closing the connection every time client side after you send a message, if you want to do that there is nothing wrong with it but you will need to send some form of identification to the server so it can tell that this is not a new connection but a old connection connecting in for a second time. This is EXACTLY what the HTTP protocol is doing and that "identification" are internet cookies.

如果您不经常传输数据,但是如果您更频繁地传输数据,则第一种选择是好的.

That first option is fine if you transmit data very infrequently but if you are doing it more often you need to keep the connection open.

基本上,您需要从客户端请求功能中进行连接和断开操作,并将打开的连接作为参数传递.

Basicly you need to take the act of connecting and disconnecting out of the client request function and pass the open connection in as a argument.

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>(都可以使用

By doing it this way the client object server side represents the client, you will have one instance of it per connected client and will remain associated with that client till he disconnects. If you want to track all of the connected clients you will need to insert them all in to some collection like a List<TcpClient> (either use a Concurrent Collection or use locking because you are multi-threaded) and then you will have a list of all clients (you will need to have the clients clean up after themselves so they remove themselves from the list after a disconnection).

这篇关于如何在多线程C#中使用TCP客户端/侦听器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆