С# несколько tcpclient одновременно

Я следил за примерами tcpclient и tcplistener на странице msdn: https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

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

Я в основном взял пример асинхронного клиента и добавил некоторый код для его запуска с помощью кнопки:

    private void button1_Click(object sender, EventArgs e)
    {
        AsynchronousClient client1 = new AsynchronousClient();
        AsynchronousClient client2 = new AsynchronousClient();

        client1.Begin("192.168.1.10");
        Thread.Sleep(5000);
        client2.Begin("192.168.1.11");
    }

этот код умирает. в конце концов, я хочу иметь возможность подключаться к нескольким частям моего оборудования и отправлять запросы каждую секунду или около того, чтобы запросить их данные, которые они могли накопить. Я не думаю, что понимаю tcp достаточно хорошо, чтобы это работало, но я думал, что должен иметь возможность асинхронно общаться с двумя клиентами. Я пытался реализовать это с помощью потоков, задач и всего остального, что я мог придумать, но я не могу надежно общаться с двумя серверами одновременно с моим приложением. Любое понимание поможет. Спасибо.

Редактировать:

Вот то, что я использую сейчас. Это безопасный способ сделать это? Я еще не написал ни о какой обработке ошибок. Кроме того, я инженер по аппаратному обеспечению и не живу в мире С#, и я пытаюсь научиться правильно использовать этот язык.

using System;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;
using System.Collections.Generic;
using System.Linq;

namespace Swordfish
{
    class SwordfishClient
    {
        private static ManualResetEvent connectDone = new ManualResetEvent(false);
        private static ManualResetEvent sendDone = new ManualResetEvent(false);
        private static ManualResetEvent receiveSizeDone = new ManualResetEvent(false);
        private static ManualResetEvent receiveMessageDone = new ManualResetEvent(false);
        private static ManualResetEvent parsedDataDone = new ManualResetEvent(false);

        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        byte[] Size = new byte[2];
        byte[] Message = new byte[1024];

        public event Action<InPacket> NewPacket;

        public void Connect(string address, int port)
        {
            if (!client.Connected)
            {
                try
                {
                    client.BeginConnect(address, port, new AsyncCallback(ConnectCallback), client);
                    connectDone.WaitOne();
                }
                catch
                {
                    return;
                }
            }
        }

        public void SendMessage(byte[] data)
        {
            if (client.Connected)
            {
                sendDone.Reset();
                client.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), client);      
                Trace.WriteLine("Waiting on SendCallback: " + sendDone.WaitOne());

                receiveSizeDone.Reset();
                client.BeginReceive(Size, 0, 2, 0, new AsyncCallback(ReceiveSizeCallback), client);                          
                Trace.WriteLine("Waiting on ReceiveSizeCallback: " + receiveSizeDone.WaitOne());

                receiveMessageDone.Reset();
                client.BeginReceive(Message, 0, BitConverter.ToUInt16(Size, 0), 0, new AsyncCallback(ReceiveMessageCallback), client);               
                Trace.WriteLine("Waiting on ReceiveMessageCallback: " + receiveMessageDone.WaitOne());

                parsedDataDone.Reset();
                parsePacket(Message, BitConverter.ToUInt16(Size, 0));
                parsedDataDone.WaitOne();         
            }
        }

        private static void ConnectCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            client.EndConnect(ar);
            connectDone.Set();
        }

        private static void ReceiveSizeCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            int bytesRead = client.EndReceive(ar);

            Trace.WriteLine("-------------------");
            Trace.WriteLine("Received Header Size: " + bytesRead);

            if (bytesRead > 0)
            {
                receiveSizeDone.Set();
            }
        }

        private static void ReceiveMessageCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            int bytesRead = client.EndReceive(ar);

            Trace.WriteLine("-------------------");
            Trace.WriteLine("Received Message Size: " + bytesRead);

            if (bytesRead > 0)
            {
                receiveMessageDone.Set();
            }
        }

        private static void SendCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            int bytesSent = client.EndSend(ar);
            Trace.WriteLine("-------------------");
            Trace.WriteLine("Bytes Sent: " + bytesSent);
            sendDone.Set();
        }

        private void parsePacket(byte[] data, int size)
        {
            Queue<byte> receivedBytes = new Queue<byte>();
            for (int i = 0; i < size - 2; i++)
            {
                receivedBytes.Enqueue(data[i]);
            }

            byte[] statusBytes = Enumerable.Range(0, 2).Select(i => receivedBytes.Dequeue()).ToArray();
            StatusCode status = (StatusCode)Enum.ToObject(typeof(StatusCode), BitConverter.ToUInt16(statusBytes, 0));

            byte[] messageBytes = Enumerable.Range(0, size - 4).Select(i => receivedBytes.Dequeue()).ToArray();

            NewPacket.Invoke(new InPacket(status, messageBytes));


            Trace.WriteLine("-------------------");
            Trace.WriteLine("Size: " + size);
            Trace.WriteLine("-------------------");
            Trace.WriteLine("Status: " + status);
            Trace.WriteLine("-------------------");

            for (int i = 0; i < data.Length; i++)
            {
                Trace.Write(data[i] + " ");
                if (i> 0 && i % 75 == 0)
                    Trace.WriteLine("");

                if(i == size - 2)
                    Trace.WriteLine("\r\n----------End of Message: This should all be zero------");
            }
            Trace.WriteLine("\r\n----------------------------------------------------------\r\n");

            for(int i =0; i < Message.Length; i++)
            {
                Message[i] = 0;
            }

            parsedDataDone.Set();
        }
    }
}

Took 7.5514 milliseconds to connect.
-------------------
Bytes Sent: 2
Waiting on SendCallback: True
-------------------
Received Header Size: 2
Waiting on ReceiveSizeCallback: True
-------------------
Received Message Size: 236
Waiting on ReceiveMessageCallback: True
-------------------
Size: 238
-------------------
Status: STATUS_LOG
-------------------
6 0 3 91 69 84 72 69 82 78 69 84 93 32 65 99 99 101 112 116 101 100 32 99 111 110 110 101 99 116 105 111 110 32 102 114 111 109 32 49 48 46 54 52 46 49 46 49 48 58 50 52 53 48 57 32 45 62 32 112 111 114 116 32 53 48 48 48 48 10 23 3 91 69 84 72 
69 82 78 69 84 93 32 65 99 99 101 112 116 101 100 32 99 111 110 110 101 99 116 105 111 110 32 102 114 111 109 32 49 48 46 54 52 46 49 46 49 48 58 50 52 53 49 48 32 45 62 32 112 111 114 116 32 53 48 48 48 49 10 23 3 91 69 84 72 69 82 78 69 84 93 
32 84 114 121 105 110 103 32 116 111 32 99 111 110 110 101 99 116 32 116 111 32 49 48 46 54 52 46 49 46 49 48 58 53 48 48 48 50 10 23 1 91 114 101 99 118 95 99 97 108 108 98 97 99 107 93 32 103 111 116 32 50 32 98 121 116 101 115 32 111 110 32 99 111 110 
102 105 103 32 112 111 114 116 10 23 0 
----------End of Message: This should all be zero------
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
----------------------------------------------------------

[ETHERNET] Accepted connection from 10.64.1.10:24509 -> port 50000
[ETHERNET] Accepted connection from 10.64.1.10:24510 -> port 50001
[ETHERNET] Trying to connect to 10.64.1.10:50002
[recv_callback] got 2 bytes on config port

person Joe    schedule 31.10.2015    source источник
comment
этот код умирает??? Что это обозначает? С предоставленным кодом и информацией мы не можем диагностировать проблему. Опубликуйте полный код и расскажите нам, чего вы хотите достичь. Возможно, вам следует использовать синхронный ввод-вывод, который проще. Примеры сокетов MSDN — это не только мусор, но и яд, потому что они ведут вас по ложному пути.   -  person usr    schedule 31.10.2015


Ответы (1)


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

Взгляните на этот пример связи TCP: https://github.com/vtortola/AynchronousTCPListener

Я надеюсь, что вы найдете это полезным.

person vtortola    schedule 31.10.2015
comment
Код сервера — это эхо-сервер tcp из xilinx sdk с использованием lwip. Я вообще не модифицировал его и, кажется, очень отзывчив, когда я просто делаю одного клиента на С#. Я проверю ваш код. - person Joe; 31.10.2015