Search code examples
c#socketstcpclientrfidtcplistener

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


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


Solution

  • 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);
        }
    }