Получать сообщения от всех сокетов, не проходя через все сокеты - PullRequest
1 голос
/ 31 марта 2019

Я пишу приложение для обмена сообщениями, используя C # и Unity для моего проекта уровня, оно использует модель клиент-сервер tcp. Я создал список сокетов, которые могут принимать сообщения, но я должен указать сокет для получения сообщения, это хорошо для тестирования, когда у меня есть только 1 клиент, но мне нужно иметь возможность обрабатывать больше соединений и выполнять циклы пытаться получить сообщение от каждого сокета кажется очень неэффективным и медленным.

Мой вопрос: как я могу получать сообщения от нескольких клиентов, не используя вышеупомянутый метод?

Я собираюсь опубликовать определенные разделы, а затем весь код, чтобы вы поняли, что я делаю.

Это поток, который занимается получением данных из сокета

    public static void Thread1()
    {
        for (int i = 0; i <= 2; i++)
        {
            byte[] b = new byte[155];
            ///////// I need to specify the socket to receive from////////
            int k = counter.numbers1[counter.i2].Receive(b);
            //////////////////////////////////////////////////////////////
            string k1 = "";

            for (int i3 = 0; i3 < k; i3++)
                k1 = k1 + Convert.ToChar(b[i3]);

            Console.WriteLine(k1);

            string sender_endpoint = k1.Substring(0, 21); ;
            string receiver_endpoint = k1.Substring(22, 21);
            string message = k1.Substring(44, 100);
            string msgtype = k1.Substring(145, 1);
            Console.WriteLine(k1.Length);
            Console.WriteLine(sender_endpoint);
            Console.WriteLine(receiver_endpoint);
            Console.WriteLine(message);
            Console.WriteLine(msgtype);

            if (msgtype == "0") //message
            {
                Console.WriteLine("000");
            }
            else if (msgtype == "1") //command
            {
                Console.WriteLine("111");
            }
        }
    }

Полный код сервера:

namespace server
{
    static class counter
    {
        public static int i2 = 0;//main listener
        public static int i4 = 0;//port number
        public static List<TcpListener> numbers = new List<TcpListener>();//listeners
        public static List<Socket> numbers1 = new List<Socket>();//sockets
    }

    class server_code
    {
        public static void Main()
        {
            string xyz123 = "x";
            Thread thread3 = new Thread(new ThreadStart(Thread3));
            Thread test_thread = new Thread(() => Test_Thread (xyz123));
            thread3.Start();
        }

        public static void Thread1()
        {
            //message reactions
            for (int i = 0; i <= 2; i++)
            {
                byte[] b = new byte[155];
                int k = counter.numbers1[counter.i2].Receive(b);
                string k1 = "";

                for (int i3 = 0; i3 < k; i3++)
                    k1 = k1 + Convert.ToChar(b[i3]);

                Console.WriteLine(k1);

                string sender_endpoint = k1.Substring(0, 21); ;
                string receiver_endpoint = k1.Substring(22, 21);
                string message = k1.Substring(44, 100);
                string msgtype = k1.Substring(145, 1);
                Console.WriteLine(k1.Length);
                Console.WriteLine(sender_endpoint);
                Console.WriteLine(receiver_endpoint);
                Console.WriteLine(message);
                Console.WriteLine(msgtype);

                if (msgtype == "0") //message
                {
                    Console.WriteLine("000");
                }
                else if (msgtype == "1") //command
                {
                    Console.WriteLine("111");
                }
            }
        }

        public static void Thread2()
        {
            //client message receiver
            var host = Dns.GetHostEntry(Dns.GetHostName());

            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    IPAddress ipAd = IPAddress.Parse(ip.ToString());

                    counter.numbers.Add(null); 
                    counter.numbers1.Add(null);

                    Console.WriteLine("");

                    Socket xyz1 = counter.numbers[counter.i2].AcceptSocket();

                    counter.numbers1[counter.i2] = xyz1;
                    ASCIIEncoding asen = new ASCIIEncoding();
                    counter.numbers1[counter.i2].Send(asen.GetBytes(counter.numbers1[counter.i2].RemoteEndPoint.ToString()));
                    Console.WriteLine("Connection accepted from " + counter.numbers1[counter.i2].RemoteEndPoint);
                    Console.WriteLine("connecting to " + counter.numbers[counter.i2].LocalEndpoint);
                    //System.Threading.Thread.Sleep(3000);

                    Thread thread1 = new Thread(new ThreadStart(Thread1));
                    thread1.Start();
                }
            }
        }

        public static void Thread3()
        {
            //new clients acception
            var host = Dns.GetHostEntry(Dns.GetHostName());

            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    for (int i = 0; i <= 10; i++)
                    {
                        Console.WriteLine(ip.ToString());
                        IPAddress ipAd = IPAddress.Parse(ip.ToString());
                        TcpListener myList = new TcpListener(ipAd, 8080);
                        myList.Start();
                        Console.WriteLine("The local endpoint is  :" + myList.LocalEndpoint);

                        Socket s = myList.AcceptSocket();//////////////////////////////////////////////
                        Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
                        Console.WriteLine("connecting to " + myList.LocalEndpoint);
                        ASCIIEncoding asen = new ASCIIEncoding();
                        counter.i2 = counter.i2 + i;
                        int portno = 8000;
                        s.Send(asen.GetBytes(portno.ToString()));

                        Console.WriteLine();
                        myList.Stop();
                        s.Close();
                        Thread thread2 = new Thread(new ThreadStart(Thread2));

                        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                        counter.numbers.Add(null);

                        TcpListener xyz = new TcpListener(ipAd, portno);

                        counter.numbers[counter.i2] = xyz;
                        //Console.WriteLine(counter.i4);//current portno

                        counter.numbers[counter.i2].Start();
                        Console.WriteLine("The local End point is  :" + counter.numbers[counter.i2].LocalEndpoint);
                        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                        thread2.Start();
                    }
                }
            }
        }
}

Полный код клиента:

public class cc : MonoBehaviour 
{
    public InputField NameField;
    private string x;
    private string y = "";
    //private int z = 0;

    static class ipadressnumber{
        public static string ipadressno = "192.168.1.250";
    }

    public void Start(){
            TcpClient tcpclnt = new TcpClient();

            tcpclnt.Connect(ipadressnumber.ipadressno,8080);
            Stream stm = tcpclnt.GetStream();

            byte[] bb=new byte[100];
            int k=stm.Read(bb,0,100);

            for (int i=0;i<k;i++){
                y = y + Convert.ToChar(bb[i]);
            }
            //Debug.Log(y);
            tcpclnt.Close();
    }

    public void OnSubmit() 
    {
        x =  NameField.text;
        //Debug.Log(x);

        try 
        {
            System.Net.IPAddress ipad = IPAddress.Parse(ipadressnumber.ipadressno);
            IPEndPoint ipLocalEndPoint = new IPEndPoint(ipad,8888);
            //TcpClient clientSocket = new TcpClient(ipLocalEndPoint);
            TcpClient tcpclnt1 = new TcpClient();
            //Debug.Log(y);
            tcpclnt1.Connect(ipadressnumber.ipadressno,int.Parse(y));
            Stream stm = tcpclnt1.GetStream();

            byte[] bb=new byte[100];
            int k=stm.Read(bb,0,100);
            string lclep = "";

            for (int i=0;i<k;i++) 
            {
                lclep = lclep + Convert.ToChar(bb[i]);
            }

            String str=x;
            ////////////format of message:(sender endpoint, recipient endpoint, message, message type, check sum/digit)
            string message = "";
            int strlen = 21;
            int msglen = 100;
            string msgtype = "0";// 0 = message, 1 = command
            lclep = Convert.ToString(lclep);
            Debug.Log (lclep);

            while (strlen > lclep.Length)
            {
                Debug.Log('1');
                lclep = lclep + "#";
            }

            string rmtep = "000.00.00.000:8000";

            while (strlen > rmtep.Length)
            {
                Debug.Log ('2');
                rmtep = rmtep + "#";
            }

            while (msglen > x.Length)
            {
                Debug.Log ('3');
                x = x + "#";
            }           

            message = message + lclep + ':' + rmtep + ':' + x + ':' + msgtype + ':';
            Debug.Log(message);

            ASCIIEncoding asen= new ASCIIEncoding();
            byte[] ba = new byte[155];
            ba=asen.GetBytes(message);

            stm.Write(ba,0,ba.Length);

            tcpclnt1.Close();
        }
        catch (Exception e) {
            Console.WriteLine("Error..... " + e.StackTrace);
        }
    }
}

Вывод такой:

192.168.1.250
The local End point is  :192.168.1.250:8080
Connection accepted from 192.168.1.250:54024
connecting to 192.168.1.250:8080

The local End point is  :192.168.1.250:8000
192.168.1.250
The local End point is  :192.168.1.250:8080

Connection accepted from 192.168.1.250:54055
connecting to 192.168.1.250:8000
192.168.1.250:54055##:000.00.00.000:8000###:message test 1 for stackoverflow####################################################################:0:
147
192.168.1.250:54055##
000.00.00.000:8000###
message test 1 for stackoverflow####################################################################
0
000

Как видите, я не получаю никаких ошибок, поэтому все, что мне нужно, - это способ получения сообщений от нескольких клиентов.

1 Ответ

0 голосов
/ 31 марта 2019

Было бы здорово иметь пример Minimal, Complete и Verifiable https://stackoverflow.com/help/mcve, но я дам возможное решение поставленной мною задачи: как прослушивать несколько сокетов и обрабатывать их сообщения одновременно.

Вы могли бы запустить один поток для каждого нужного вам сокета, этот поток чтения прочитал бы все сообщение и отправил бы список безопасного потока в другой поток, который я назову потоком обработки. Этот последний поток будет применять вашу бизнес-логику к данным, считываемым вашим сокетом, генерировать ответ и отправлять его в другой поток: Поток писателя.

Socker -> Считыватели -> Процессор -> Writer

Не запускайте ваши потоки, как в методах Thread3 и Thread2, это требует слишком много ресурсов процессора и может замедлить ваше размещение. Заранее создайте темы и начните затем в соответствующем порядке.

...