- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在尝试让我的服务器应用程序在我的客户端断开连接时在标签中显示一条消息。
此时标签在客户端启动时会显示已连接客户端的IP地址,但当客户端关闭时,IP地址仍会显示在标签中。
到目前为止,我已经尝试过这些方法但没有任何运气:
// DETECT IF CLIENT DISCONNECTED
//METHOD 1
if (bytesRead == 0)
{
ClientIPLabel.Text = "(No Clients Connected)";
break;
}
//METHOD 2
if (!tcpListener.Pending())
{
ClientIPLabel.Text = "(No Clients Connected)";
}
//METHOD 3
if (tcpClient.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
{
ClientIPLabel.Text = "(No Clients Connected)";
}
我确定这可能是我遗漏的一些简单的东西,我只是不知道它可能是什么。
编辑:我发现了一些解决方法,当我单击关闭客户端应用程序的按钮时,客户端会在关闭前向服务器发送一条消息。服务器知道,如果它收到此特定消息(在本例中为“SHUTDOWN CLIENT”),则将“ClientIPLabel.text”中的文本更改为“(未连接客户端)”
这在大多数情况下确实有效,但它有点像 hack,如果客户端由于错误或崩溃等原因关闭。服务器不知道它已断开连接,因此它仍会显示最后已知的已发送 IP。
第二次编辑: 所以看来解决方法对我不起作用。将其添加到我的项目后,出于某种原因,无论我的客户端向服务器发送什么消息都会导致显示“(未连接客户端)”消息。
我的客户端实际上仍处于连接状态并接收消息,但“ClientIPLabel”标记不正确
第三次编辑:这是一个片段,显示了我如何设置我的客户端以按照我在下面的一条评论中详细说明的方式将消息发送到服务器:
private void SendMessage(string msg)
{
NetworkStream clientStream = ConsoleClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
第四次编辑:我的服务器代码,以及我直接从客户端关闭按钮获取客户端断开连接消息的临时解决方法:
public partial class Server : Form
{
private TcpListener tcpListener;
private Thread listenThread;
private delegate void WriteMessageDelegate(string msg);
public Server()
{
InitializeComponent();
Server();
}
// WAIT FOR CLIENT
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
// GET CLIENT IP ADDRESS
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
string clientIPAddress = "" + IPAddress.Parse(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
ClientIPLabel.Text = clientIPAddress;
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
// COMMUNICATE WITH CLIENT
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
// CHECK FOR CLIENT DISCONNECT
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
第 5 次编辑: 我已经更新了我的代码,并且(几乎)实现了心跳定时器,但它仍然没有完全正确地设置......这是我的代码:
// CHECK FOR CLIENT DISCONNECT
// SHUTDOWN BUTTON PRESSED
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
// CHECK FOR CONNECTION FAILED
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
HandleClientComm("Check for connection");
}
catch (Exception)
{
Invoke((MethodInvoker)delegate
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
“(无客户端连接)”消息在计时器后自动弹出到我的服务器上,无论我的客户端是否已断开连接,因此它没有正确捕获异常。
我已经尝试实现 interceptwind 的建议,因为他写了它,但出于某种原因,我应该有 catch (Exception e)
我只有在摆脱 e
写成catch (Exception)
。如果我将 e
留在那里,我会收到一条警告,提示 “变量 'e' 已声明但从未使用过”
。
此外,我知道 interceptwind 编写他的示例是为了使用我的 SendMessage() 方法,但该方法只在我的客户端中使用,所以我更改了代码以尝试使用我的 HandleClientComm() 方法,所以我想知道是否这就是无法正常工作的原因。我试过改变一些东西,但似乎仍然无法正常工作。 5 秒后我仍然收到消息“(没有客户端连接)”,即使我的客户端仍然连接并正常运行。
第 6 次编辑: 我试图调整我的 HandleClientComm()
方法来发送消息,但我显然错过了一些东西,因为我的“心跳计时器“仍在将我的 ClientIPLabel.text 切换为“(未连接客户端)”,即使我的客户端仍处于连接状态。
这是我的代码:
// COMMUNICATE WITH CLIENT
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] message = new byte[4096];
byte[] buffer = encoder.GetBytes("Send Message");
int bytesRead;
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
// START HEARTBEAT TIMER
System.Timers.Timer heartbeatTimer = new System.Timers.Timer();
heartbeatTimer.Interval = 5000;
heartbeatTimer.Elapsed += heartbeatTimer_Elapsed;
heartbeatTimer.Start();
// CHECK FOR CLIENT DISCONNECT
// SHUTDOWN BUTTON PRESSED
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
// CHECK FOR CONNECTION FAILED
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
HandleClientComm("Check for connection");
}
catch (Exception)
{
Invoke((MethodInvoker)delegate
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
最佳答案
鉴于OP限制Server不能向Client发送消息,另一种方式是Client每X秒(例如5秒)向Server发送一次心跳消息。
然后服务器将检查它是否在过去的 Y 秒(例如 30 秒)内收到了来自客户端的任何消息。如果没有,则意味着客户端已断开连接。
客户代码
public Client()
{
...
//After connection, CALL ONCE ONLY
Timer heartbeatTimer = new System.Timers.Timer();
heartbeatTimer.Interval = 5000; //5 seconds
heartbeatTimer.Elapsed += heartbeatTimer_Elapsed;
heartbeatTimer.Start();
}
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
SendMessage("Heartbeat");
}
服务器代码
bool receiveHeartBeat = false;
public Server()
{
...
//After connection, CALL ONCE ONLY
Timer checkHeartbeatTimer = new System.Timers.Timer();
checkHeartbeatTimer.Interval = 30000; //30 seconds
checkHeartbeatTimer.Elapsed += checkHeartbeatTimer_Elapsed;
checkHeartbeatTimer.Start();
}
void checkHeartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if(receiveHeartBeat)
{
Invoke((MethodInvoker)delegate //prevent cross-thread exception
{
ClientIPLabel.Text = "Connected";
});
}
else
{
Invoke((MethodInvoker)delegate //prevent cross-thread exception
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
void WriteMessage(string msg)
{
receiveHeartBeat = true;
// rest of your code
}
关于c# - 当 TCPClient 断开连接时显示消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34456104/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!