Tôi đã chiến đấu với một vấn đề trong cả 3 ngày tôi không thể tìm thấy giải pháp nào, xin hãy giúp :)
Tôi làm việc với ngôn ngữ Visual Studio 2010 và C#.Làm cách nào để kiểm tra kết nối bị hỏng của TCPClient sau khi được kết nối?
Tôi có một thiết bị hoạt động như một máy chủ, gửi một số dữ liệu trong một khoảng thời gian rất bất thường (không thể xác định thời gian chờ đọc).
Tôi đã viết một máy khách TCP để kết nối với máy chủ đó và đọc dữ liệu. Nó hoạt động OK, tuy nhiên khi có sự cố với mạng và máy chủ không khả dụng (ví dụ khi tôi cắm cáp mạng từ máy tính của tôi), mất khoảng 10 giây để ứng dụng "thông báo" không có kết nối với máy chủ và ném một ngoại lệ. (Tôi không biết tại sao chính xác 10 giây? Nó được xác định ở đâu? Tôi có thể thay đổi nó không?)
Tôi muốn phản ứng nhanh hơn - giả sử sau một giây sau khi kết nối bị hỏng.
Googling cho câu trả lời tuy nhiên không cung cấp cho tôi bất kỳ giải pháp làm việc.
Mã thử nghiệm dưới đây, tôi cố gắng làm cho nó trên 2 chủ đề: một là đọc dữ liệu, thứ hai là tìm kiếm trạng thái kết nối và nên báo động cho tôi khi nó bị hỏng. Nó không hoạt động cho cả lớp TCPClient lẫn Socket. Tôi đã cố gắng để đọc/ghi một số dữ liệu với tcpClient.SendTimeout = 100;
và stream.WriteTimeout = 100;
nhưng nó dường như không hoạt động.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCPClient
{
class Program
{
static volatile bool _continue = true;
static TcpClient tcpClient;
static NetworkStream stream;
static void Main(string[] args)
{
try
{
//client thread - listen from server
Thread tcpListenThread = new Thread(TcpListenThread);
tcpListenThread.Start();
//connection checking thread
Thread keepAliveThread = new Thread(KeepAliveThread);
keepAliveThread.Start();
while (_continue)
{
if (Console.ReadLine() == "q")
{
_continue = false;
}
}
keepAliveThread.Join(2000);
if (keepAliveThread.IsAlive)
{
Console.WriteLine("Thread keepAlive has been aborted...");
keepAliveThread.Abort();
}
tcpListenThread.Join(2000);
if (tcpListenThread.IsAlive)
{
Console.WriteLine("Listen thread has been aborted...");
tcpListenThread.Abort();
}
}
catch (Exception ex)
{
Console.WriteLine("\n" + ex.Message);
}
Console.WriteLine("\nHit any key to quit...");
Console.Read();
}
private static void TcpListenThread()
{
string server = "172.20.30.40";
int port = 3000;
try
{
using (tcpClient = new TcpClient())
{
tcpClient.Connect(server, port);
if (tcpClient.Connected)
Console.WriteLine("Successfully connected to server");
using (stream = tcpClient.GetStream())
{
while (_continue)
{
Byte[] data = new Byte[1024];
Int32 bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}, responseData);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Listen thread exception! " + ex.Message);
}
}
private static void KeepAliveThread()
{
while (_continue)
{
if (tcpClient != null)
{
try
{
//...what to put here to check or throw exception when server is not available??...
}
catch (Exception ex)
{
Console.WriteLine("Disconnected...");
}
}
Thread.Sleep(1000); //test for connection every 1000ms
}
}
}
}
Edit:
@ câu trả lời Carsten của: mặc dù có vẻ đầy hứa hẹn, giải pháp này không làm việc ...
tôi đã ứng dụng thử nghiệm đơn giản nhất cho rằng:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCPClientTest
{
class Program
{
static void Main(string[] args)
{
try
{
string server = "172.20.30.40";
int port = 3000;
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(server, port);
int i = 0;
while (true)
{
// This is how you can determine whether a socket is still connected.
bool blockingState = tcpClient.Client.Blocking;
try
{
byte[] tmp = new byte[1];
tcpClient.Client.Blocking = false;
tcpClient.Client.Send(tmp, 0, 0);
Console.WriteLine("Connected!");
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
Console.WriteLine("Still Connected, but the Send would block");
else
{
Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
{
tcpClient.Client.Blocking = blockingState;
}
Console.WriteLine("Connected: {0} ({1})", tcpClient.Client.Connected, i++);
Thread.Sleep(1000);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Global exception: {0}", ex.Message);
}
}
}
}
Kết quả đang theo dõi, hiển thị:
Đã kết nối!
Đã kết nối: True
cộng với số đơn đặt hàng của tôi sau mỗi một giây. Khi tôi ngắt kết nối cáp mạng, phải mất 8 giây để bắt đầu in:
Đã ngắt kết nối: mã lỗi 10054!
Đã kết nối: False
do đó 8 giây Tôi không biết rằng kết nối bị mất. Có vẻ như ping là lựa chọn tốt nhất ở đây, nhưng tôi sẽ thử nghiệm một giải pháp khác.
Có thể trùng lặp: [Làm cách nào tôi có thể kiểm tra xem ổ cắm (TCP) có được ngắt kết nối trong C#?] Hay không (http://stackoverflow.com/questions/515458/how-can-i-check-whether-a -tcp-socket-is-disconnect-in-c) – ladenedge
@ladenedge Có thể trùng lặp ... ngoại trừ việc này có nhiều mã ví dụ hơn để giúp các ppl khác học theo cách khác.Tôi biết bình luận của bạn là cũ, tuy nhiên nó là bực bội khi những người như bạn làm cho vô dụng và khuyến khích các ý kiến không hiệu quả. – Euthyphro