|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Async socket connection ends up in Unable to read data from....inconvinience Hi, I've written a class for client-socket connection, but I get a lot of times the error message "Unable to read data from the transport connection" when restart reading the stream with socket.BeginRead in the Sub SocketIncomingMsg. I'm debugging now for weeks, but I can't detect where it's going wrong. the part of code where it fails: Try RnetworkStream.BeginRead(myReceivedData, 0, myReceivedData.Length, New AsyncCallback(AddressOf SocketIncomingMsg), RnetworkStream) Catch ex As Exception 'THIS ONE OFTEN FAILES 'UNABLE TO READ DATA FROM THE TRANSPORT CONNECTION DisconnectSocket() End Try Can someone please review my code and point me in the right direction. This thing is driving me nuts.. The Complete code: Imports System.Net.Sockets Imports System.Text Imports System.Threading Namespace TCPIP Public Enum Status Disconnected = 0 Listening = 1 Connected = 3 Connecting = 2 End Enum Public Class TCPClientSock Private mState As TCPIP.Status Private mTcpClient As TcpClient Private RnetworkStream As NetworkStream Public Event DataReceived(ByVal Data As String) Public Event CommError(ByVal ErrorMessage As Exception) Public Event StatusChanged(ByVal State As TCPIP.Status) Private myReceivedData() As Byte Public Sub New() mState = TCPIP.Status.Disconnected RaiseEvent StatusChanged(mState) End Sub Public ReadOnly Property Connected() As Boolean Get Return (mState = Status.Connected) End Get End Property Public Sub Shutdown() Me.DisconnectSocket() End Sub Public Function ConnectSocket(ByVal Server As String, ByVal Port As Int16) As Boolean Try mTcpClient = Nothing mTcpClient = New TcpClient 'make connection mState = TCPIP.Status.Connecting RaiseEvent StatusChanged(mState) mTcpClient.Connect(Server, Port) 'connected RnetworkStream = mTcpClient.GetStream If RnetworkStream.CanRead Then mState = TCPIP.Status.Connected ReDim myReceivedData(mTcpClient.ReceiveBufferSize) 'start reading stream RnetworkStream.BeginRead(myReceivedData, 0, myReceivedData.Length, New AsyncCallback(AddressOf SocketIncomingMsg), RnetworkStream) RaiseEvent StatusChanged(mState) Return True End If Catch e As Exception ' error while connecting RaiseEvent CommError(e) 'not connected mState = TCPIP.Status.Disconnected RaiseEvent StatusChanged(mState) Try mTcpClient.Close() Catch End Try End Try End Function Private Sub SocketIncomingMsg(ByVal arMsg As IAsyncResult) Dim intCount As Integer Dim lus As Int16 Dim myMessage As String = "" Try intCount = RnetworkStream.EndRead(arMsg) If intCount < 1 Then 'socket closed DisconnectSocket() End If Catch ex As Exception End Try For lus = 0 To intCount - 1 myMessage &= Chr(myReceivedData(lus)) Next 'process message in background ThreadPool.QueueUserWorkItem(AddressOf Me.ProcessReceivedData, CType(myMessage, Object)) 'restart reading stream Try RnetworkStream.BeginRead(myReceivedData, 0, myReceivedData.Length, New AsyncCallback(AddressOf SocketIncomingMsg), RnetworkStream) Catch ex As Exception 'THIS ONE OFTEN FAILES 'UNABLE TO READ DATA FROM THE TRANSPORT CONNECTION DisconnectSocket() End Try End Sub Private Sub ProcessReceivedData(ByVal Data As Object) If CStr(Data) <> "" Then RaiseEvent DataReceived(CStr(Data)) End Sub Public Sub DisconnectSocket() Try RnetworkStream.Close() Catch ex As Exception End Try Try mTcpClient.Close() Catch ex As Exception End Try Try mTcpClient = Nothing Catch ex As Exception End Try mState = TCPIP.Status.Disconnected RaiseEvent StatusChanged(mState) End Sub Public Sub SendSocketData(ByVal Data As String) Try Dim SnetworkStream As NetworkStream = mTcpClient.GetStream() Dim sendBytes(Data.Length - 1) As Byte Dim lus As Int16 For lus = 0 To Data.Length - 1 sendBytes(lus) = Asc(Data.Substring(lus, 1)) Next SnetworkStream.Write(sendBytes, 0, sendBytes.Length) Catch e As Exception RaiseEvent CommError(e) End Try End Sub End Class Public Class TCPServerSock 'removed due to irrelevance End Class End Namespace Hi,
From your description, when you use the the code you provided in your application, the code that below will generate the error as below. "Unable to read data from the transport connection" The occurred when the SocketIncomingMsg method is reentry after the first reading operating finished. Here is the make a simple test for your code, but I can not reproduce the problem. [Server] Imports System Imports System.Net.Sockets Imports System.Text Public Class TcpTimeServer Private Const portNum As Integer = 13 Public Overloads Shared Function Main(ByVal args() As [String]) As Integer Dim done As Boolean = False Dim listener As New TcpListener(portNum) listener.Start() While Not done Console.Write("Waiting for connection...") Dim client As TcpClient = listener.AcceptTcpClient() Console.WriteLine("Connection accepted.") Dim ns As NetworkStream = client.GetStream() Dim byteTime As Byte() = _ Encoding.ASCII.GetBytes(DateTime.Now.ToString()) Try ns.Write(byteTime, 0, byteTime.Length / 2) System.Threading.Thread.Sleep(3000) ns.Write(byteTime, byteTime.Length / 2, byteTime.Length / 2) ns.Close() client.Close() Catch e As Exception Console.WriteLine(e.ToString()) End Try End While listener.Stop() Return 0 End Function 'Main End Class 'TcpTimeServer [Client] Public Class Form1 Dim WithEvents c As TCPIP.TCPClientSock Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click c = New TCPIP.TCPClientSock() If c.ConnectSocket("machinename", 13) Then MsgBox("Connected") End If End Sub Private Sub c_DataReceived(ByVal Data As String) Handles c.DataReceived MsgBox(Data) End Sub End Class You may have a try and let me know if the code above will reproduce the problem at your side. I look forward to hearing from you. Also I suggest try to check the RnetworkStream.CanRead in method SocketIncomingMsg, just as you do in the method ConnectSocket. Best regards, Peter Huang Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. Peter,
the code you send me works just fine.. To clear out more specific on my problem, The error doesn't occur after the first read operation is finished, as far as I can see, it's completely random (it should have a reason, but I can't track it down) Sometimes it's after the 4th read operation, sometimes it's after the 500th read operation, sometime it's after the ... read operation. In other words, sometimes it fails after 5 minutes, sometimes after 1 hour, sometimes after 1 day. In my application, the socket-connection stays connected 24/7 (it least it should do so), at least every 15 minutes I will receive some data from the server, sometimes less as 15 minutes. The socket connection will use a gprs connection to the server, so some small latency can occur, but i think the OS should take care of this... (Is this right?) What reason can there be that this error occurs when RnetworkStream.BeginRead(myReceivedData, 0, myReceivedData.Length, New AsyncCallbackAddressOf SocketIncomingMsg),RnetworkStream) Is it possible that a networkstream 'suddenly' becomes 'unreadable' so that I have to check RnetworkStream.CanRead every time when doing the .BeginRead? What to do when .CanRead = False, can the stream become readable again after some time? I don't want to reconnect my socket everytime to the server again. If it can recover, how to do so. On the server-side, the socket is still connected when the client fails the ..BeginRead This thing is driving me nuts.... Kind regards, Arno Broeders Hi Arno,
It is hard to guess what is the root cause the scenario without reproduce the problem. From the description, I understand the Exception throw is IOException. But from the MSDN doucment in the scenario below, the IOException may be thrown when the NetworkStream.BeginRead IOException The underlying Socket is closed. -or- There was a failure while reading from the network. -or- An error occurred when accessing the socket. See the Remarks section for more information. Note If you receive an IOException, check the InnerException property to determine if it was caused by a SocketException. If so, use the ErrorCode property to obtain the specific error code, and refer to the Windows Sockets version 2 API error code documentation in MSDN for a detailed description of the error. NetworkStream.BeginRead Method http://msdn2.microsoft.com/en-us/library/system.net.sockets.networkstream.be ginread.aspx So I think you may try to print out the detailed Exception/InnerException information as below. Try Catch ex As Exception Debug.Print(ex.ToString()) Debug.Print(ex.InnerException.ToString()) DisconnectSocket() End Try Also please check all the code in both Server and Client about close socket/connection. Because you can not reproduce the problem with my server code, you may try to add Log code line before every socket related call. e.g. Debug.Print "Socket accept" Debug.Print "Socket read" Debug.Print "Socket close" To monitor if there is any possibility that the socket is closed by server side. Here is the error list may occur in the Win32 ErrorCode. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/win sock/recv_2.asp or the path to the C++ header Winsock2.h e.g.<this may differ based on your installation> C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include Best regards, Peter Huang Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. Okay, I implemented the logging in my application and found 2 reasons for
errors. 14-9-2006 10:18:14 - System.IO.IOException: Unable to read data from the transport connection. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state) at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) --- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at DataCollectorService.TCPIP.TCPClientSock.SocketIncomingMsg(IAsyncResult arMsg) in S:\VS.2003\Projects\iView\PartialCollectors\OMRON-Collector\ClsTCPIP.vb:line 86 14-9-2006 10:18:14 - System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state) at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) This one is strange because the socket on the server was still opened. Maybe it's my 3com internet NAT-router that will close socket connections that stay open for a long time. Can this be? Second error is: 14-9-2006 9:35:22 - System.ObjectDisposedException: Cannot access a disposed object named "System.Net.Sockets.NetworkStream". Object name: "System.Net.Sockets.NetworkStream". at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at DataCollectorService.TCPIP.TCPClientSock.SocketIncomingMsg(IAsyncResult arMsg) in S:\VS.2003\Projects\iView\PartialCollectors\OMRON-Collector\ClsTCPIP.vb:line 86 This one is bugging me the most.. How can it be that .EndRead on the stream is succesfull and when doing a new .BeginRead the stream is suddenly disposed. Peter can you please advise me? Kind regards, Arno Show quoteHide quote ""Peter Huang" [MSFT]" <v-phu***@online.microsoft.com> schreef in bericht news:j6EAwpW1GHA.400@TK2MSFTNGXA01.phx.gbl... > Hi Arno, > > It is hard to guess what is the root cause the scenario without reproduce > the problem. > From the description, I understand the Exception throw is IOException. > > But from the MSDN doucment in the scenario below, the IOException may be > thrown when the NetworkStream.BeginRead > IOException > The underlying Socket is closed. > -or- > There was a failure while reading from the network. > -or- > An error occurred when accessing the socket. See the Remarks section for > more information. > > Note > If you receive an IOException, check the InnerException property to > determine if it was caused by a SocketException. If so, use the ErrorCode > property to obtain the specific error code, and refer to the Windows > Sockets version 2 API error code documentation in MSDN for a detailed > description of the error. > > NetworkStream.BeginRead Method > http://msdn2.microsoft.com/en-us/library/system.net.sockets.networkstream.be > ginread.aspx > > So I think you may try to print out the detailed Exception/InnerException > information as below. > Try > Catch ex As Exception > Debug.Print(ex.ToString()) > Debug.Print(ex.InnerException.ToString()) > DisconnectSocket() > End Try > Also please check all the code in both Server and Client about close > socket/connection. > Because you can not reproduce the problem with my server code, you may try > to add Log code line before every socket related call. > e.g. > Debug.Print "Socket accept" > Debug.Print "Socket read" > Debug.Print "Socket close" > > To monitor if there is any possibility that the socket is closed by server > side. > > Here is the error list may occur in the Win32 ErrorCode. > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/win > sock/recv_2.asp > or > the path to the C++ header Winsock2.h > e.g.<this may differ based on your installation> > C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include > > Best regards, > > Peter Huang > > Microsoft Online Community Support > ================================================== > When responding to posts, please "Reply to Group" via your newsreader so > that others may learn and benefit from your issue. > ================================================== > This posting is provided "AS IS" with no warranties, and confers no > rights. > Hi Arno,
Thanks very much for your efforts and information. From your information, you will encounter two exceptions. 1. System.IO.IOException: Unable to read data from the transport connection. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host As the error description, this means the underlying socket is closed by remote host. But due to the complex in network environment this may be caused by many possibility. Your assumption also may be one of the possibility. Because the network path between your machine A and the Server B may include many other network devices, e.g. Router, Proxy, Firewall..... 2. System.ObjectDisposedException: Cannot access a disposed object named "System.Net.Sockets.NetworkStream". From the error, the networkstream is disposed. But we are still trying to access to it. So far it is hard to guess what is the root cause. A possible cause it that after the End Read, the underlying socket may be closed, so the networkstream is disposed too and then we are trying to access it so get the exception. Since so far you can not reproduce the problem with the simple server code I send to you. I suggest you try to run your Server and Client code on two directly connect machines or even one machine, if there are no error occur for a long time e.g. one week. We should consider your code is OK but is not robust and error handling enough. Commonly network application will need more error handling than common application, especially the wireless network environment. A common way is to handle all the possible exception and do proper action, so that we can built a robust application. BTW: for such GRPS network, I understand it is low bandwidth network and not very relialbe(it may be disconnected due to gprs signals) compared to LAN, I suggest you sent a small data in one time so that a End Read will finish more quick. e.g. If the socket is closed, we may try to reconnect to the server and try a predefined time to write error log. This depends on concrete implement policy. The main idea is to retry when error occurred, and retry a few times to reconnect or event report error to End User and stop doing. Just as IE, when we are trying to connect to a web site, when it has gone through its error handle steps, it will show an error page to End User. If you still have any concern, please feel free to let me know. I look forward to hearing from you. Best regards, Peter Huang Microsoft Online Partner Support When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ===================================================== Business-Critical Phone Support (BCPS) provides you with technical phone support at no charge during critical LAN outages or "business down" situations. This benefit is available 24 hours a day, 7 days a week to all Microsoft technology partners in the United States and Canada. This and other support options are available here: BCPS: https://partner.microsoft.com/US/technicalsupport/supportoverview/40010469 Others: https://partner.microsoft.com/US/technicalsupport/supportoverview/ If you are outside the United States, please visit our International Support page: http://support.microsoft.com/common/international.aspx. ===================================================== This posting is provided "AS IS" with no warranties, and confers no rights. |
|||||||||||||||||||||||