我使用StreamSocket
连接到套接字服务器,我使用无限循环来读取数据。每条数据都以'\n\n'
结尾。该片段如下所示。但是,我无法知道套接字是否仍然存在,并且每次服务器关闭连接时,ReadAsync()
都会抛出异常。如何在连接关闭时收到通知?
public async Task<string> ReadData() {
StreamReader reader = new StreamReader(socket.InputStream.AsStreamForRead());
char[] ch = new char[65536];
int i = 0;
while (IsConnected) {
await reader.ReadAsync(ch, i++, 1);
if (i > 1 && ch[i - 1] == '\n' && ch[i - 2] == '\n') break;
}
return new StringBuilder().Append(ch, 0, i - 2).ToString();
}
答案 0 :(得分:1)
每次服务器关闭连接时,ReadAsync()都会抛出异常。
大多数服务器都应该如此。 TCP / IP有一个相当昂贵的四部分握手来优雅地关闭连接,但从服务器的角度来看,等待回收这些资源需要很长时间。所以,很多服务器只是“猛烈抨击”。连接关闭,导致SocketError.ConnectionReset
错误。
正如我在socket error handling博客文章中描述的那样,如果沟通状态是这样的,你会考虑一个优雅的关闭&#34;在那时适当,那么你也应该在同一点接受ConnectionReset
的异常。 (在您的情况下,适当的&#34;关闭&#34;点是指消息是否已使用\n\n
完成。)
如何在连接关闭时收到通知?
您将获得ConnectionReset
例外(如果它突然关闭),或者您的ReadAsync
将返回0
(如果它正常关闭)。
...然而
如何知道套接字连接是否仍然存在?
只有一种可靠的方法可以检测套接字连接是否仍然可行:将数据写入其中。我在half-open problem上的博文中详细介绍了这一点。
由于套接字通信中这个相当有趣的怪癖,像while (IsConnected)
这样的代码是一种反模式。相反,您需要有一个定期轮询循环,基于计时器将数据发送到另一方。
P.S。如果可能的话,使用SignalR而不是原始套接字。他们为你做了所有艰难的事情。
答案 1 :(得分:0)
每次服务器关闭连接时,ReadAsync()都会抛出异常。
抛出异常是因为发生非正常断开连接。因此,在关闭服务器端的连接之前,确保套接字上存在没有任何挂起的读取或写入操作,那么应该没有异常。您可以参考StreamSocket class的备注部分了解更多详情。
如何在连接关闭时收到通知?
另一方可以检测到正常的套接字闭包为0长度读取。也就是说,它只是像常规的流末端一样。 Here是一个类似的帖子供您参考。
因此,您可以使用以下代码检查您的方案中是否已关闭连接:
public async Task<string> ReadData()
{
StreamReader reader = new StreamReader(socket.InputStream.AsStreamForRead());
char[] ch = new char[65536];
int i = 0;
while (true)
{
await reader.ReadAsync(ch, i++, 1);
// break when the connection is closed or data ends with '\n\n'
if (ch[i - 1] == '\0' || (i > 1 && ch[i - 1] == '\n' && ch[i - 2] == '\n')) break;
}
if (ch[i - 1] == '\0')
{
// do something here when the connection is closed
}
else
{
return new StringBuilder().Append(ch, 0, i - 2).ToString();
}
}
以下是我验证的整个方法:
class FunctionDictionary
{
/// <summary>
/// Internal dictionary that will store the function delegates as Object.
/// </summary>
private Dictionary<string, Object> m_Map = new Dictionary<string, object>();
/// <summary>
/// Add method to dictionary for specified key. Encapsulated method has no parameters.
/// </summary>
public void Add<TResult>(string key, Func<TResult> function)
{
m_Map.Add(key, function);
}
/// <summary>
/// Get method for specified key. Encapsulated method has no parameters.
/// </summary>
public Func<TResult> Function<TResult>(string key)
{
return (Func<TResult>)m_Map[key];
}
/// <summary>
/// Add method to dictionary for specified key. Encapsulated method has one parameters.
/// </summary>
public void Add<T1, TResult>(string key, Func<T1, TResult> function)
{
m_Map.Add(key, function);
}
/// <summary>
/// Get method for specified key. Encapsulated method has one parameters.
/// </summary>
public Func<T, TResult> Function<T, TResult>(string key)
{
return (Func<T, TResult>)m_Map[key];
}
public void Add<T1, T2, TResult>(string key, Func<T1, T2, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, TResult>(string key, Func<T1, T2, T3, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, TResult>(string key, Func<T1, T2, T3, T4, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, TResult>(string key, Func<T1, T2, T3, T4, T5, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> function)
{
m_Map.Add(key, function);
}
public void Add<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(string key, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> function)
{
m_Map.Add(key, function);
}
public Object this[string key]
{
get
{
return m_Map[key];
}
}
public Func<T1, T2, TResult> Function<T1, T2, TResult>(string key)
{
return (Func<T1, T2, TResult>)m_Map[key];
}
public Func<T1, T2, T3, TResult> Function<T1, T2, T3, TResult>(string key)
{
return (Func<T1, T2, T3, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, TResult> Function<T1, T2, T3, T4, TResult>(string key)
{
return (Func<T1, T2, T3, T4, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, TResult> Function<T1, T2, T3, T4, T5, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, TResult> Function<T1, T2, T3, T4, T5, T6, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, TResult> Function<T1, T2, T3, T4, T5, T6, T7, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>)m_Map[key];
}
public Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> Function<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(string key)
{
return (Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>)m_Map[key];
}
}