Reputation: 90570
When trying to receive a string or file content (as string) via TCP I am stuck with an issue wher the receiving works in general, but the line
print("TCP -> Data received:\n" + file + "\n\n" + totalrecbytes + " Bytes");
is kind of stalled until I activelly disconnect from the server side. Than it works as expected.
I debugged and receiving the data inside the
while ((recBytes = netstream.Read(bytes, 0, bytes.Length)) > 0)
loop works just fine. It also ends the loop in the correct moment. But after that simply nothing happens. I get no errors, am not "trapped" in any loop but also do not get the expected output of
print("TCP -> Data received:\n" + file + "\n\n" + totalrecbytes + " Bytes");
until I disconnect from the server side. Than I see the expected output and the client is disconnected.
Here is the implementation (original source)
private Thread _tcpThread;
private TcpClient _socketConnection;
public void Connect()
{
try
{
_tcpThread = new Thread(ReciveDataClient);
_tcpThread.IsBackground = true;
_tcpThread.Start();
}
catch (Exception e)
{
print(e.Message);
}
}
private void ReciveDataClient()
{
try
{
_socketConnection = new TcpClient("xxx.xxx.xxx.xxx", 54321);
print(this, "TCP -> Connection Success!");
}
catch (Exception e)
{
print("connection error: " + e.Message)
return;
}
try
{
var bytes = new byte[BUFFER_SIZE];
while (_socketConnection.Connected)
{
if (_socketConnection.Available <= 0) continue;
// Get a stream object for reading
var netstream = _socketConnection.GetStream();
int totalrecbytes = 0;
int recBytes;
string file = "";
// Read incomming stream into byte arrary.
while ((recBytes = netstream.Read(bytes, 0, bytes.Length)) > 0)
{
var incommingData = new byte[recBytes];
Array.Copy(bytes, 0, incommingData, 0, recBytes);
// Convert byte array to string message.
var serverMessage = Encoding.ASCII.GetString(incommingData);
file += serverMessage;
totalrecbytes += recBytes;
}
print("TCP -> Data received:\n" + file + "\n\n" + totalrecbytes + " Bytes");
netstream.Close();
}
print("TCP -> connection was terminated by the server");
}
catch (Exception e)
{
print(e.Message)
return;
}
}
I would expect that I can maintain the connection alive but still receive the data correctly and communicate with the server on a persistent TCP connection.
What am I missing or doing wrong here?
The only workarround I could find so far is allways disconnect from the server side after sending data and in my code wrap the whole ReceiveDataClient
in a while
loop like
private void ReciveDataClient()
{
while (true)
{
try
{
_socketConnection = new TcpClient(_server.ToString(), _server.Port);
//...
in order to immediately start a new connection after the server sent some data and disconnected the client.
Upvotes: 1
Views: 266
Reputation: 90570
Thanks to the help of Damien_The_Unbeliever and Immersive I could figure it out. It really helps to read the docs from time to time especially if it is the first time you use something ^^
NetworkStream.Read is a blocking call and as the doc states
returns: The number of bytes read from the NetworkStream, or 0 if the socket is closed.
so ofcourse the while
loop actually never terminated.
So adopting the example provided there worked for me except that if the server ended the connection I got another issue so instead of checking for _socketConnection.IsConnected
I used the marked answer from this post so all together this works for me now
private Thread _tcpThread;
private TcpClient _socketConnection;
public void Connect()
{
if(_socketConnection != null) return;
try
{
_tcpThread = new Thread(ReciveDataClient);
_tcpThread.IsBackground = true;
_tcpThread.Start();
}
catch (Exception e)
{
print("TCP -> Thread error: " + e.Message);
}
}
public void Disconnect()
{
if(_socketConnection = null) return;
_tcpThread.Abort();
}
private void ReciveDataClient()
{
try
{
_socketConnection = new TcpClient("xxx.xxx.xxx.xxx", 54321);
print(this, "TCP -> Connection Success!");
}
catch (Exception e)
{
print("TCP -> connection error: " + e.Message)
return;
}
try
{
while(true)
{
// Get a stream object for reading
var netstream = _socketConnection.GetStream();
//Check if still connected
if(_socketConnection.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if( _socketConnection.Client.Receive( buff, SocketFlags.Peek ) == 0 )
{
// Server disconnected or connection lost
break;
}
}
// Check to see if this NetworkStream is readable.
if(myNetworkStream.CanRead)
{
byte[] myReadBuffer = new byte[BUFFER_SIZE];
StringBuilder myCompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
int totalBytesReceived = 0;
// Incoming message may be larger than the buffer size.
do
{
numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
totalBytesReceived += numberOfBytesRead;
}
while(myNetworkStream.DataAvailable);
// Print out the received message to the console.
print("TCP -> Data received:\n" + myCompleteMessage.ToString() + "\n\n" + totalrecbytes + " Bytes");
}
else
{
//Prevent a direct loop
Thread.Sleep(100);
}
}
print("TCP -> connection was terminated by the server");
}
catch(ThreadAbortException)
{
print("TCP -> Disconnected");
}
catch(Exception e)
{
print(e.Message)
}
// Clean up
_socketConnection?.Close();
_socketConnection?.Dispose();
_socketConnection = null;
}
Upvotes: 1