净插座并没有远程断开应对? [英] .Net Socket doesn't respond to remote disconnect?

查看:168
本文介绍了净插座并没有远程断开应对?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个小的(C#)客户端,使用TCP / IP连接到远程服务器发送数据的应用程序。我使用标准.NET的TcpClient对象,并想离开连接从客户端开口,因为我经常在提交的数据包到服务​​器。然而,可能的是,服务器可关闭该连接,在这种情况下,我需要知道发送我的下一个数据包之前重新连接。

使用Wireshark的,我可以看到(只)以下的对话时,服务器将终止连接:

服务器>>> FIN, ACK
                ACK <<<客户

我做的没有的看到的是我的客户响应与它自己的FIN,即可完成连接关闭。其结果是,我的客户端程序,只发现了发送下一个数据包后,连接已断开。

有没有什么办法可以设置的TcpClient或其基础插槽,以完成断开连接,并提供一些反馈,这样我的客户code知道发送下一个数据包之前,重新连接?

添加响应如下评论: 我送code是很简单 - 即保持的TcpClient和的NetworkStream成员变量的对象,有一个包含(基本上)成员函数如下:

 布尔发= FALSE;
byte []的缓冲区= Encoding.UTF8.GetBytes(dataString);
而(!发送)
{
    尝试
    {
        m_outStream.Write(缓冲液,0,buffer.Length);
        发送= TRUE;
    }
    赶上(例外前)
    {
        如果(!m_outStream = NULL){m_outStream.Dispose(); }
        m_client =新的TcpClient(AddressFamily.InterNetwork);
        m_client.Connect(ip地址,ipPort);
        m_outStream = m_client.GetStream();
    }
}
 

使用m_client和m_outStream初始化,这只是执行单程每次。然后使用Wireshark的,我可以看到服务器发送一个数据包标记 FIN,ACK 与客户端与 ACK 响应。

下一次我打电话给我的功能,将数据发送出去与 PSH,ACK 和服务器 RST,ACK 但不读取输入数据。不发生异常的客户端。

然后我打电话给我的功能,第二次,并且引发异常导致重新启动了连接。

解决方案

一般来说,你应该能够使用连接 TcpCient财产例如:

下面请参见:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx

不过:<​​/ P>

  

因为连接的属性只反映了国家   连接,最近操作的,你应该尝试发送   或接收消息,以确定当前状态。该消息之后   发送失败,则该属性不再返回true。注意,这   行为是设计使然。你不能可靠地测试的状态   连接,因为,在测试和一个发送之间的时间/接收,   该连接可能已经丢失。您的code应当承担   套接字连接,并妥善处理失败的传输。

请尝试以下方法,以确保连接标记保持最近的状态:

  VAR的TcpClient =新的TcpClient();
tcpClient.Connect();

VAR流= tcpClient.GetStream();

//缓冲区大小需要是&GT; 0
INT []缓冲液=新INT [1];
stream.Read(缓冲液,0,0);

如果(!tcpClient.Connected)
    // 做一点事
 

基于反编译

应该可以读取流 0 字节,至少有一个在.NET框架 TcpClient的<不检查/ code>是prevents这一点。然而它可能不是大声在从该框架调用实际上从网络流中读取的外部code

请务必处置两者的的TcpClient 您完成后,处置的TcpClient 不处置的所以你需要待办事项这个手动,后来所有的资源都释放出来(后GC)。

I'm writing a small (C#) client application that sends data using a TCP/IP connection to a remote server. I'm using the standard .Net TcpClient object and want to leave the connection open from the client end as I am regularly submitting data packets to the server. However, it is possible that the server may close the connection, in which case I need to know to re-connect before sending my next packet.

Using Wireshark, I can see (only) the following dialogue when the server terminates the connection:

server >>> FIN, ACK
                ACK <<< client

What I do not see is my client responding with a FIN of its own, to complete the connection shutdown. The result is that my client program only finds out that the connection is down after sending the next data packet.

Is there any way I can set up TcpClient or its underlying Socket so as to complete the disconnect, and provide some feedback so that my client code knows to re-connect before sending the next packet?

Added in response to comment below: My sending code is very simple - the object that maintains the TcpClient and NetworkStream member variables, has a member function containing (essentially) the following:

bool sent = false;
byte[] buffer = Encoding.UTF8.GetBytes(dataString);
while (!sent)
{
    try
    {
        m_outStream.Write(buffer, 0, buffer.Length);
        sent = true;
    }
    catch (Exception ex)
    {
        if (m_outStream != null) { m_outStream.Dispose(); }
        m_client = new TcpClient(AddressFamily.InterNetwork);
        m_client.Connect(ipAddress, ipPort);
        m_outStream = m_client.GetStream();
    }
}

With m_client and m_outStream initialized, this simply performs a single pass every time. Then using Wireshark I can see the server send a packet with flags FIN, ACK to which the client responds with ACK.

The next time I call my function, the data is sent out with PSH, ACK, and the server responds with RST, ACK but does not read the incoming data. No exception is raised by the client.

Then I call my function a second time, and an exception is raised causing the connection to be re-started.

解决方案

In general you should be able to use the Connected property on the TcpCient instance:

See here:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx

However:

Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost. Your code should assume the socket is connected, and gracefully handle failed transmissions.

Try the following to make sure the Connected flag holds the most recent state:

var tcpClient = new TcpClient ();
tcpClient.Connect();

var stream = tcpClient.GetStream();

// buffer size need to be > 0
int[] buffer = new int[1];
stream.Read(buffer, 0, 0);

if(!tcpClient.Connected)
    // do something

Based on decompilation it should be possible to read 0 bytes from a stream, at least there is no check in the .NET Framework TcpClient that prevents this. However it might not be aloud in the external code that is called from the framework to actually read from the network stream.

Be sure to Dispose of both the TcpClient and the Stream after your done, disposing the TcpClientdoes not dispose of the Stream so you need todo this manually, afterwards all resources are freed up (after GC).

这篇关于净插座并没有远程断开应对?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆