I'm building a (LAN) network application, so there is always the possibility that a connection will be disconnected, for various possible reasons. I am trying to think of a good design for handling this issue, such that it doesn't affect the rest of the application. I wrote a quick thing to try to do it, but I think it can be enhanced a lot. I appreciate your help and experience about the best way to handle this issue.
我正在构建一个(LAN)网络应用程序,因此出于各种可能的原因,总是有可能断开连接。我试图想出一个处理这个问题的好设计,这样它不会影响应用程序的其余部分。我写了一个快速的尝试去做,但我认为它可以增强很多。感谢您对处理此问题的最佳方式的帮助和体验。
This is my first trial:
这是我的第一次试用:
class ConnectionWrapper {
NetworkStream stream;
StreamReader reader;
Endpoint endPoint;
bool endOfStream;
int maxRetries = 5;
public void connect() {
// ... code to initialize a (TCP) socket to endPoint
this.stream = new NetworkStream(socket, true);
this.reader = new StreamReader(stream);
}
string readNextMsg() {
try {
string msg = reader.ReadLine();
if (msg == "EOF") endOfStream = true;
return msg;
}
catch (IOException e) {
Exception ex = e;
while (maxRetries-- > 0) {
try { connect(); ex = null; }
catch (Exception e2) { ex = e2; }
}
if (x != null) throw ex;
}
}
}
Not very elegant, and probably not the best that can be done. Could you please share your experience, and may be even suggest an existing library?
不是很优雅,可能不是最好的。您能否分享一下您的经验,甚至可以建议现有的图书馆?
Thank you.
2 个解决方案
#1
I honestly don't think you should let the connection wrapper contain logic to handle its own connection policy. I think this should be done from outside of this class, and especially not in the catch statement. Have some kind of ConnectionController object to deal with whether the connection should be retried once it fails.
老实说,我认为你不应该让连接包装器包含处理自己的连接策略的逻辑。我认为这应该从这个类的外部完成,特别是在catch语句中。有一些ConnectionController对象来处理一旦失败就应该重试连接。
#2
I was going to edit my post, but this should be completely separate from my last one.
我打算编辑我的帖子,但这应该与我的上一篇完全分开。
Your logic is all wrong in my opinion, you should have a thread within the ConnectionWrapper which spins on the StreamReader pulling off messages and placing them on a queue. This queue then notifies listeners of a change. The listeners then go and retrieve the data themselves and decide what needs to be done with them.
在我看来,你的逻辑是完全错误的,你应该在ConnectionWrapper中有一个线程,它在StreamReader上旋转,拉出消息并将它们放在队列中。然后,此队列通知侦听器更改。然后,监听器会自行检索数据并决定需要对它们执行的操作。
class ConnectionWrapper {
NetworkStream stream;
StreamReader reader;
Endpoint endPoint;
bool endOfStream;
int maxRetries = 5;
ArrayList arr;
public void connect() {
// ... code to initialize a (TCP) socket to endPoint
this.stream = new NetworkStream(socket, true);
this.reader = new StreamReader(stream);
}
private void initReceiverThread() {
String line;
while(stream.isConnected() && (line = reader.readLine()) != null) {
// notify observers of a change
arr.add(line);
}
}
}
This is pseudo-code I warn you, I've never done this in C#. A typical reader actually waits on a readLine statement, so the while loop won't go crazy. It's also best to put initReceiverThread code in a Thread, that way it won't block the rest of the application. By notifying the observers of a change they can then go and get the ArrayList by doing something like myConnectionWrapper.getMessages(); which will return an ArrayList, but also clearing out the ArrayList at the same time, like so:
这是伪代码我警告你,我从未在C#中做过这个。典型的读者实际上等待readLine语句,因此while循环不会发疯。最好将initReceiverThread代码放在Thread中,这样它就不会阻塞应用程序的其余部分。通过向观察者通知更改,他们可以通过执行类似myConnectionWrapper.getMessages()的操作来获取ArrayList;它将返回一个ArrayList,同时也清除ArrayList,如下所示:
public ArrayList getMessages() {
ArrayList temp = arr;
arr.clear();
return temp;
}
That way you get ALL of the messages and clear them off the queue.
这样您就可以获得所有消息并将其从队列中清除。
I've written network clients before, and this is the general design of one. You'll have two threads constantly spinning, one to receiver messages, and one to send them.
我以前写过网络客户端,这是一个通用的设计。你将有两个线程不断旋转,一个接收消息,一个发送它们。
The logic should be dealt with some kind of manager code to determine whether to continue, or reconnect or whatever you want to do.
逻辑应该用某种管理器代码来处理,以确定是继续,还是重新连接或者你想做什么。
#1
I honestly don't think you should let the connection wrapper contain logic to handle its own connection policy. I think this should be done from outside of this class, and especially not in the catch statement. Have some kind of ConnectionController object to deal with whether the connection should be retried once it fails.
老实说,我认为你不应该让连接包装器包含处理自己的连接策略的逻辑。我认为这应该从这个类的外部完成,特别是在catch语句中。有一些ConnectionController对象来处理一旦失败就应该重试连接。
#2
I was going to edit my post, but this should be completely separate from my last one.
我打算编辑我的帖子,但这应该与我的上一篇完全分开。
Your logic is all wrong in my opinion, you should have a thread within the ConnectionWrapper which spins on the StreamReader pulling off messages and placing them on a queue. This queue then notifies listeners of a change. The listeners then go and retrieve the data themselves and decide what needs to be done with them.
在我看来,你的逻辑是完全错误的,你应该在ConnectionWrapper中有一个线程,它在StreamReader上旋转,拉出消息并将它们放在队列中。然后,此队列通知侦听器更改。然后,监听器会自行检索数据并决定需要对它们执行的操作。
class ConnectionWrapper {
NetworkStream stream;
StreamReader reader;
Endpoint endPoint;
bool endOfStream;
int maxRetries = 5;
ArrayList arr;
public void connect() {
// ... code to initialize a (TCP) socket to endPoint
this.stream = new NetworkStream(socket, true);
this.reader = new StreamReader(stream);
}
private void initReceiverThread() {
String line;
while(stream.isConnected() && (line = reader.readLine()) != null) {
// notify observers of a change
arr.add(line);
}
}
}
This is pseudo-code I warn you, I've never done this in C#. A typical reader actually waits on a readLine statement, so the while loop won't go crazy. It's also best to put initReceiverThread code in a Thread, that way it won't block the rest of the application. By notifying the observers of a change they can then go and get the ArrayList by doing something like myConnectionWrapper.getMessages(); which will return an ArrayList, but also clearing out the ArrayList at the same time, like so:
这是伪代码我警告你,我从未在C#中做过这个。典型的读者实际上等待readLine语句,因此while循环不会发疯。最好将initReceiverThread代码放在Thread中,这样它就不会阻塞应用程序的其余部分。通过向观察者通知更改,他们可以通过执行类似myConnectionWrapper.getMessages()的操作来获取ArrayList;它将返回一个ArrayList,同时也清除ArrayList,如下所示:
public ArrayList getMessages() {
ArrayList temp = arr;
arr.clear();
return temp;
}
That way you get ALL of the messages and clear them off the queue.
这样您就可以获得所有消息并将其从队列中清除。
I've written network clients before, and this is the general design of one. You'll have two threads constantly spinning, one to receiver messages, and one to send them.
我以前写过网络客户端,这是一个通用的设计。你将有两个线程不断旋转,一个接收消息,一个发送它们。
The logic should be dealt with some kind of manager code to determine whether to continue, or reconnect or whatever you want to do.
逻辑应该用某种管理器代码来处理,以确定是继续,还是重新连接或者你想做什么。