Tôi có hai ứng dụng đơn giản:C# phát hiện tcp ngắt kết nối
Một ứng dụng máy chủ mà chờ đợi trên một cổng tcp cụ thể đối với một khách hàng để kết nối. Sau đó, lắng nghe những gì anh ấy nói, gửi lại một số phản hồi và THAM KHẢO khách hàng đó.
Ứng dụng biểu mẫu kết nối với ứng dụng máy chủ, sau đó nói điều gì đó, sau đó chờ phản hồi và ngắt kết nối khỏi máy chủ, sau đó hiển thị phản hồi trong biểu mẫu.
Mặc dù ứng dụng máy chủ dường như cư xử một cách chính xác (tôi đã thử nghiệm nó với Telnet và tôi thấy ý kiến phản hồi và tôi thấy các ngắt xảy ra ngay sau khi những phản hồi), việc áp dụng hình thức tuy nhiên dường như không để ý ngắt kết nối khỏi máy chủ. (TcpClient.Connected dường như vẫn đúng ngay cả sau khi máy chủ đã ngắt kết nối)
Câu hỏi của tôi là: tại sao TcpClient.Connected vẫn đúng và làm cách nào để biết khi nào máy chủ bị ngắt kết nối?
Đây là mã đầy đủ của tôi:
Mẫu ứng dụng:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Sender
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void sendButton_Click(object sender, EventArgs e)
{
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Parse("127.0.0.1"), 81);
responseLabel.Text = "waiting for response...";
responseLabel.Invalidate();
// write request
NetworkStream networkStream = tcpClient.GetStream();
byte[] buffer = (new ASCIIEncoding()).GetBytes("Hello World! ");
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
// read response
Thread readThread = new Thread(new ParameterizedThreadStart(ReadResponse));
readThread.Start(tcpClient);
}
void ReadResponse(object arg)
{
TcpClient tcpClient = (TcpClient)arg;
StringBuilder stringBuilder = new StringBuilder();
NetworkStream networkStream = tcpClient.GetStream();
bool timeout = false;
DateTime lastActivity = DateTime.Now;
while (tcpClient.Connected && !timeout)
{
if (networkStream.DataAvailable)
{
lastActivity = DateTime.Now;
while (networkStream.DataAvailable)
{
byte[] incomingBuffer = new byte[1024];
networkStream.Read(incomingBuffer, 0, 1024);
char[] receivedChars = new char[1024];
(new ASCIIEncoding()).GetDecoder().GetChars(incomingBuffer, 0, 1024, receivedChars, 0);
stringBuilder.Append(receivedChars);
}
}
else
{
if (DateTime.Now > lastActivity.AddSeconds(60))
timeout = true;
}
System.Threading.Thread.Sleep(50);
}
Invoke((MethodInvoker)delegate
{
responseLabel.Text = "Response from Listener:\n" + stringBuilder.ToString();
responseLabel.Invalidate();
});
if (timeout)
{
Console.Write("A timeout occured\n");
networkStream.Close();
tcpClient.Close();
}
}
}
}
máy chủ ứng dụng:
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
using System.Threading;
namespace Listener
{
class Program
{
static void Main(string[] args)
{
var tcpListener = new TcpListener(IPAddress.Any, 81);
tcpListener.Start();
Thread clientThread = new Thread(new ParameterizedThreadStart(Listen));
clientThread.Start(tcpListener);
}
static void Listen(object arg)
{
TcpListener tcpListener = (TcpListener)arg;
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
clientThread.Start(tcpClient);
}
}
static void HandleClient(object arg)
{
TcpClient tcpClient = (TcpClient)arg;
StringBuilder stringBuilder = new StringBuilder();
ASCIIEncoding encoder = new ASCIIEncoding();
DateTime lastActivity = DateTime.Now;
// read request
NetworkStream networkStream = tcpClient.GetStream();
int timeout = 5; // gives client some time to send data after connecting
while (DateTime.Now < lastActivity.AddSeconds(timeout) && stringBuilder.Length==0)
{
if (!networkStream.DataAvailable)
{
System.Threading.Thread.Sleep(50);
}
else
{
while (networkStream.DataAvailable)
{
lastActivity = DateTime.Now;
byte[] incomingBuffer = new byte[1024];
networkStream.Read(incomingBuffer, 0, 1024);
char[] receivedChars = new char[1024];
encoder.GetDecoder().GetChars(incomingBuffer, 0, 1024, receivedChars, 0);
stringBuilder.Append(receivedChars);
}
}
}
string request = stringBuilder.ToString();
// write response
string response = "The listener just received: " + request;
byte[] outgoingBuffer = encoder.GetBytes(response);
networkStream.Write(outgoingBuffer, 0, outgoingBuffer.Length);
networkStream.Flush();
networkStream.Close();
tcpClient.Close();
}
}
}
đã đồng ý, ổ cắm sẽ là một tùy chọn tốt hơn để sử dụng tại đây – XikiryoX
NetworkStream chính nó sử dụng một Ổ cắm (mặc dù nó không phải là một đĩa công cộng). Làm thế nào tôi có thể sử dụng nó? Nói cách khác: Nếu tôi đang sử dụng Socket, làm thế nào tôi sẽ tiến hành để biết nếu khách hàng đã bị ngắt kết nối? –
Hãy xem Thăm dò ý kiến .. Tôi đồng ý rằng Network Stream và TcpClient sử dụng Socket nhưng chúng cung cấp một giao diện cấp cao .. Ổ cắm tuy nhiên là socket .. những gì bạn thấy là những gì bạn nhận được :) –