2015-10-31 5 views
0

я следовал TcpClient и TcpListener примеров на странице MSDN: https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspxC# несколько tcpclients одновременно

Я пытаюсь подключиться к нескольким частям оборудования, которое у меня есть эхо сервер 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 достаточно хорошо, чтобы сделать эту работу, но я подумал, что я должен поговорить с двумя клиентами асинхронно. Я попытался реализовать это с помощью потоков, задач и всего остального, о чем я могу думать, но я не могу надежно разговаривать с двумя серверами одновременно с моим приложением. Любое понимание поможет. Благодарю.

Edit:

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

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 
+0

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

ответ

0

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

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

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

+0

Код сервера - это echo-сервер tcp из silk xilinx с использованием lwip. Я вообще не модифицировал его и, кажется, супер отзывчив, когда я просто делаю одного клиента в C#. Проверьте свой код. – Joe

Смежные вопросы