tcpclient problem

T

Theo

Hi,
I am using a tcpclient and a tcplistener to send and receive packets. The
client sends a packet and the listener replies with another one. I can send
2 packets and get an answer from the listener but it fails to send a third
packet. I don't get any error messages. The client sends the packet
successfully but it never arrives to the listener. This only happens when I
send the packets one straight after the other. If I place a delay of 2 sec
between each transition all packets will be received successfully.

This is how I read the buffer stream:
-----------------------------------------------------------------------
Private Sub ReceiveData(ByVal ar As IAsyncResult)

SyncLock tcpclient.GetStream

CountBytesRead = tcpclient.GetStream.EndRead(ar)

End SyncLock

MeamoryStream.Write(readBuffer, 0, BytesRead)

...

SyncLock tcpclient.GetStream

tcpclient.GetStream.BeginRead(readBuffer, 0,
tcpclient.ReceiveBufferSize, AddressOf ReceiveData, Nothing)

End SyncLock

End Sub

-------------------------------------------------------------------

I assume that the third packet has already arrived before
tcpClient.GetStream.BeginRead is invoked but I cannot see why this should be
a problem.

If anyone can advise me on that please do.

Thanks
 
8

89fsg987g

The EndRead method completes the asynchronous read operation started in the
BeginRead <frlrfsystemnetsocketsnetworkstreamclassbeginreadtopic.htm>
method.
Before calling BeginRead, you need to create a callback method that
implements the AsyncCallback <frlrfsystemasynccallbackclasstopic.htm>
delegate. This callback method executes in a separate thread and is called
by the system after BeginRead returns. The callback method must accept the
IAsyncResult <frlrfsystemiasyncresultclasstopic.htm> returned from the
BeginRead method as a parameter.
Within the callback method, call the AsyncState
<frlrfsystemiasyncresultclassasyncstatetopic.htm> method of the IAsyncResult
to obtain the state object passed to the BeginRead method. Extract the
receiving NetworkStream <frlrfsystemnetsocketsnetworkstreamclasstopic.htm>
from this state object. After obtaining the NetworkStream, you can call the
EndRead method to successfully complete the read operation and return the
number of bytes read.
The EndRead method will block until data is available. The EndRead method
will read as much data as is available up to the number of bytes specified
in the size parameter of the BeginRead method. If the remote host shuts down
the Socket <frlrfsystemnetsocketssocketclasstopic.htm> connection and all
available data has been received, the EndRead method will complete
immediately and return zero bytes.
To obtain the received data, call the AsyncState method of the IAsyncResult,
and extract the buffer contained in the resulting state object.
Note If you receive a IOException <frlrfsystemioioexceptionclasstopic.htm>
check the InnerException <frlrfsystemexceptionclassinnerexceptiontopic.htm>
property to determine if it was caused by a SocketException
<frlrfsystemnetsocketssocketexceptionclasstopic.htm>. If so, use ErrorCode
<frlrfsystemnetsocketssocketexceptionclasserrorcodetopic.htm> to obtain the
specific error code. Once you have obtained this code, you can refer to the
Windows Socket Version 2 API error code documentation in MSDN for a detailed
description of the error.
Example
[Visual Basic, C#, C++] In the following example, myReadCallback is provided
to BeginRead <frlrfsystemnetsocketsnetworkstreamclassbeginreadtopic.htm> as
the callback method. EndRead is implemented in myReadCallback to complete
the asynchronous read call started by BeginRead.
[Visual Basic]
Public Shared Sub myReadCallBack(ar As IAsyncResult)

Dim myNetworkStream As NetworkStream = CType(ar.AsyncState,
NetworkStream)
Dim myReadBuffer(1024) As Byte
Dim myCompleteMessage As [String] = ""
Dim numberOfBytesRead As Integer

numberOfBytesRead = myNetworkStream.EndRead(ar)
myCompleteMessage = [String].Concat(myCompleteMessage,
Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead))

' message received may be larger than buffer size so loop through until
you have it all.
While myNetworkStream.DataAvailable

myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, New
AsyncCallback(AddressOf
NetworkStream_ASync_Send_Receive.myReadCallBack), myNetworkStream)
End While


' Print out the received message to the console.
Console.WriteLine(("You received the following message : " +
myCompleteMessage))
End Sub 'myReadCallBack

'Entry point which delegates to C-style main Private Function
Public Overloads Shared Sub Main()
Main(System.Environment.GetCommandLineArgs())
End Sub
[C#]

public static void myReadCallBack(IAsyncResult ar ){

NetworkStream myNetworkStream = (NetworkStream)ar.AsyncState;
byte[] myReadBuffer = new byte[1024];
String myCompleteMessage = "";
int numberOfBytesRead;

numberOfBytesRead = myNetworkStream.EndRead(ar);
myCompleteMessage =
String.Concat(myCompleteMessage,
Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));

// message received may be larger than buffer size so loop through until
you have it all.
while(myNetworkStream.DataAvailable){

myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length,
new
AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack),
myNetworkStream);

}

// Print out the received message to the console.
Console.WriteLine("You received the following message : " +
myCompleteMessage);
}
[C++]
static void myReadCallBack(IAsyncResult* ar) {
NetworkStream* myNetworkStream =
__try_cast<NetworkStream*>(ar->AsyncState);
Byte myReadBuffer[] = new Byte[1024];
String* myCompleteMessage = S"";
int numberOfBytesRead;

numberOfBytesRead = myNetworkStream->EndRead(ar);
myCompleteMessage =
String::Concat(myCompleteMessage,
Encoding::ASCII->GetString(myReadBuffer, 0, numberOfBytesRead));

// message received may be larger than buffer size so loop through until
you have it all.
while (myNetworkStream->DataAvailable) {
AsyncCallback* pasync = new AsyncCallback(0, &myReadCallBack);
myNetworkStream->BeginRead(myReadBuffer, 0, myReadBuffer->Length,
pasync,
myNetworkStream);
}

// Print out the received message to the console.
Console::WriteLine(S"You received the following message : {0}",
myCompleteMessage);
}
[JScript] No example is available for JScript. To view a Visual Basic, C#,
or C++ example, click the Language Filter button in the upper-left corner of
the page.
 
T

Theo

Tnx for the reply,
however your example will not work for two reasons:

1. By placing the ReadBegin call into this while loop you allow the stream to be read only while bytes arrive at the port continuously. If there is a time gap between two data transmissions which practically means that NetworkStram.DataVailable = False the code will not go inside the loop and therefore the ReadBegin will not start.

Suppose that 2000 bytes are sent to the port. The myReadCallBack sub will be called twice reading approximately 1000 bytes each time. At the second call though and after the stream has been read it will be empty and no data will be available. The while loop will not execute and the tcpclient will not listen to the port for incoming bytes.

Practically I was doing the same thing without having a loop based on the DataAvailable property.

2. By using the while loop you read the receive buffer until it is empty and then you convert the bytes to string and concatenate them. However I am not transmitting string objects but serialized classes, so even if this method worked I still couldn't use it because if I concatenate all the incoming bytes I will not be able to deserialize them later.

Here follows my exact ReadBuffer sub:

Private Sub ReceiveData(ByVal ar As IAsyncResult)
Try
Dim BytesRead As Integer
Dim Data As New IO.MemoryStream

SyncLock client.GetStream
BytesRead = client.GetStream.EndRead(ar)
End SyncLock

'Place the received bytes into a memorystream
'and raise an event to deserialize the stream
Data.Write(readBuffer, 0, BytesRead)
RaiseEvent DataReceived(Me, Data)

SyncLock client.GetStream
client.GetStream.BeginRead(readBuffer, 0, client.ReceiveBufferSize,_
AddressOf ReceiveData, client.GetStream)
End SyncLock
Catch e As Exception
RaiseEvent ErrorOccured(e)
End Try
End Sub

Thanks


Ï said:
The EndRead method completes the asynchronous read operation started in the
BeginRead <frlrfsystemnetsocketsnetworkstreamclassbeginreadtopic.htm>
method.
Before calling BeginRead, you need to create a callback method that
implements the AsyncCallback <frlrfsystemasynccallbackclasstopic.htm>
delegate. This callback method executes in a separate thread and is called
by the system after BeginRead returns. The callback method must accept the
IAsyncResult <frlrfsystemiasyncresultclasstopic.htm> returned from the
BeginRead method as a parameter.
Within the callback method, call the AsyncState
<frlrfsystemiasyncresultclassasyncstatetopic.htm> method of the IAsyncResult
to obtain the state object passed to the BeginRead method. Extract the
receiving NetworkStream <frlrfsystemnetsocketsnetworkstreamclasstopic.htm>
from this state object. After obtaining the NetworkStream, you can call the
EndRead method to successfully complete the read operation and return the
number of bytes read.
The EndRead method will block until data is available. The EndRead method
will read as much data as is available up to the number of bytes specified
in the size parameter of the BeginRead method. If the remote host shuts down
the Socket <frlrfsystemnetsocketssocketclasstopic.htm> connection and all
available data has been received, the EndRead method will complete
immediately and return zero bytes.
To obtain the received data, call the AsyncState method of the IAsyncResult,
and extract the buffer contained in the resulting state object.
Note If you receive a IOException <frlrfsystemioioexceptionclasstopic.htm>
check the InnerException <frlrfsystemexceptionclassinnerexceptiontopic.htm>
property to determine if it was caused by a SocketException
<frlrfsystemnetsocketssocketexceptionclasstopic.htm>. If so, use ErrorCode
<frlrfsystemnetsocketssocketexceptionclasserrorcodetopic.htm> to obtain the
specific error code. Once you have obtained this code, you can refer to the
Windows Socket Version 2 API error code documentation in MSDN for a detailed
description of the error.
Example
[Visual Basic, C#, C++] In the following example, myReadCallback is provided
to BeginRead <frlrfsystemnetsocketsnetworkstreamclassbeginreadtopic.htm> as
the callback method. EndRead is implemented in myReadCallback to complete
the asynchronous read call started by BeginRead.
[Visual Basic]
Public Shared Sub myReadCallBack(ar As IAsyncResult)

Dim myNetworkStream As NetworkStream = CType(ar.AsyncState,
NetworkStream)
Dim myReadBuffer(1024) As Byte
Dim myCompleteMessage As [String] = ""
Dim numberOfBytesRead As Integer

numberOfBytesRead = myNetworkStream.EndRead(ar)
myCompleteMessage = [String].Concat(myCompleteMessage,
Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead))

' message received may be larger than buffer size so loop through until
you have it all.
While myNetworkStream.DataAvailable

myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, New
AsyncCallback(AddressOf
NetworkStream_ASync_Send_Receive.myReadCallBack), myNetworkStream)
End While


' Print out the received message to the console.
Console.WriteLine(("You received the following message : " +
myCompleteMessage))
End Sub 'myReadCallBack

'Entry point which delegates to C-style main Private Function
Public Overloads Shared Sub Main()
Main(System.Environment.GetCommandLineArgs())
End Sub
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top