The operation is not allowed on non-connected sockets. System.Net.Sockets

36 views Asked by At
string DeviceTCPIP = "168.34.15.249";
string BackData;
string TextMessage;
int DevicePort = 5600;

void ReadCard()
{
     this.threadListen = new Thread((ThreadStart)(() =>
     {
         while (true)
         {
             try
             {
                 using (TcpClient tcpClient = new())
                 {
                     tcpClient.BeginConnect(DeviceTCPIP, DevicePort, null, null).AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));
                     TextMessage = "%DD001**CR";
                     byte[] bytes = Encoding.ASCII.GetBytes(TextMessage);
                     bytes[bytes.Length - 1] = (byte)13;
                     NetworkStream stream = tcpClient.GetStream();
                     stream.Write(bytes, 0, bytes.Length);
                     byte[] buffer = new byte[2048];
                     MemoryStream memoryStream = new();
                     tcpClient.Client.ReceiveTimeout = 500;
                     int count;
                     do
                     {
                         try
                         {
                             count = stream.Read(buffer, 0, buffer.Length);

                             memoryStream.Write(buffer, 0, count);
                         }
                         catch (IOException ex)
                         {
                             if (!(ex.InnerException is SocketException innerException) || innerException.ErrorCode != 10060)
                                 throw ex;
                             count = 0;
                         }
                     }
                     while (count > 0);
                     BackData = Encoding.ASCII.GetString(memoryStream.ToArray());
                     if (BackData.Contains("match string"))
                     {
                         Console.WriteLine(BackData);
                     }
                 }
             }
             catch (Exception ex)
             {
                 ErrorData = ex.Message.ToString();
             }
             Thread.Sleep(100);
         }
     }));
     this.threadListen.Start();
}

I try read data from device for RFID number. But I receive following error. Also some of my tried I can receive RFID data correctly. However frequently throw following error. What can I do to fix the error?

error image

1

There are 1 answers

0
Charlieface On BEST ANSWER

There are many things wrong with your code.

  • Primarily using BeginConnect without an EndConnect.
  • If you'd used Async with await you wouldn't have had this issue in the first place, as it's much easier to write.
  • Blocking using WaitOne instead of using the callback properly.
  • Use tasks instead of threads.
  • Should use UTF8 instead of ASCII.
  • stream needs a using.
  • Use throw; not throw ex; in a catch otherwise you wipe the stack trace.
  • Better yet, just use a catch when condition.
  • Having said that, it makes no sense to catch a 10060 IO exception on a TCP stream. You need to restart the connection.
  • Don't use ToArray on a MemoryStream, just use GetBuffer to get the underlying buffer along with the Length.
  • Rather than writing a manual read loop, just use stream.CopyToAsync.
  • You should probably have some mechanism for shutting down the loop, such as a CancellationToken.
void ReadCard()
{
    Task.Run(TcpLoop);
}

async Task TcpLoop()
{
    while (true)
    {
        try
        {
            using TcpClient tcpClient = new();
            using (var cts = new CancellationTokenSource(1000))
            {
                await tcpClient.ConnectAsync(DeviceTCPIP, DevicePort, cts.Token);
            }
            tcpClient.Client.ReceiveTimeout = 500;
            TextMessage = "%DD001**C\r";
            byte[] bytes = Encoding.UTF8.GetBytes(TextMessage);
            using NetworkStream stream = tcpClient.GetStream();
            await stream.WriteAsync(bytes.AsMemory());

            MemoryStream memoryStream = new();
            stream.CopyToAsync(memoryStream);
            BackData = Encoding.UTF8.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
            if (BackData.Contains("match string"))
            {
                Console.WriteLine(BackData);
            }
        }
        catch (Exception ex)
        {
            ErrorData = ex.Message;
        }
        await Task.Delay(100);
    }
}