error of reading data in socket programming - c#

i wrote a console application. i used socket programming .
i get error in below cod. transfer speed of data is 10ms . after a period of time i get a error on " while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)" line .
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
NetworkStream stream = tcpClient.GetStream();
String data = null;
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
...
}
error :
An unhandled exception of type 'System.IO.IOException' occurred in
System.dll Additional information: Unable to read data from the
transport connection: A connection attempt failed because the
connected party did not properly respond after a period of time, or
established connection failed because connected host has failed to
respond.

When you do IO stuff or network stuff, your code needs to be able to handle excpetional circumstances, so say with a socket, the server suddenly shuts down their end of a connection, your code needs to be able to handle that. And your code isn't doing anything with that exception.
To do this you need to put your code in a try/catch block
try
{
// put socket code stuff here
}
catch(IOException ioe)
{
// put excpetion code here.
}
Hope this helps.

Related

Server Timeout C#

So, I'm developing a client-side application in C# that connects to a server side application (also written in C#). To begin with, I am just trying to get the applications to successfully communicate with one another. Currently, I have both the client and server running on the same device.
Server Side
On the server side, I'm using a TcpListener to accept a socket, printing out that it has connected for debugging purposes, receiving a request, and sending a response. The code can be found below:
Server Side Code:
while (true)
{
// Accept a new connection
Socket socket = socketListener.AcceptSocket();
if (socket.Connected)
{
Console.WriteLine("\nClient Connected!!\n==================\nClient IP {0}\n", socket.RemoteEndPoint);
// Make a byte array and receive data from the client
byte[] receive = new byte[1024];
_ = socket.Receive(receive, receive.Length, 0);
// Convert byte to string
string buffer = Encoding.ASCII.GetString(receive);
string response = "Test response";
int numBytes = 0;
try
{
if (socket.Connected)
{
if ((numBytes = socket.Send(data, data.Length, 0)) == -1)
Console.WriteLine("Socket Error: cannot send packet");
else
Console.WriteLine("No. of bytes sent {0}", numBytes);
}
else
{
Console.WriteLine("Connection Dropped...");
}
}
catch (Exception e)
{
Console.WriteLine("An exception has occurred: " + e.ToString());
}
}
}
Client Side
On the client side, I'm using a TcpClient to connect to the server using an IP address (In this case it's 127.0.0.1), establishing a NetworkStream object, sending a request, and reading a response.
Client-Side Code:
private static readonly TcpClient socket = new TcpClient();
private const string IP = "127.0.0.1";
private const int PORT = 46495;
static void Main(string[] args)
{
try
{
socket.Connect(IP, PORT);
}
catch (Exception)
{
Console.WriteLine("Error connecting to the server.");
return;
}
NetworkStream stream = socket.GetStream();
stream.ReadTimeout = 2000;
string request = "Test Request";
byte[] bytes = Encoding.UTF8.GetBytes(request);
stream.Write(bytes, 0, bytes.Length);
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
try
{
string response = reader.ReadToEnd();
Console.WriteLine(response);
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
The Output
On the server side, everything appears to be fine. The client connects successfully with the expected IP address, I get the expected request, and the correct response appears to have been sent successfully.
The client-side is where it gets more complicated. Where I would expect the "Test Response" response, instead I get a SocketException that from what I understand indicates a timeout??? The full output can be found below:
System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or an established connection failed because the connected host has failed to respond...
---> System.Net.Sockets.SocketException (10060): A connection attempt failed because the connected party did not properly respond after a period of time, or an established connection failed because the connected host has failed to respond.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
at Client.Client.Main(String[] args) in C:\Dev\Project Orange Sunshine\Project Orange Sunshine\Client\Client.cs:line 38
What I have tried
To begin I wanted to ensure that my server was in fact sending a response in the first place. To test this, I tried accessing the server application through a web browser. Sure enough, I got a blank page with the expected "Test Response" text in the top left corner. This, to me, indicates my server application is working as expected.
Through some googling, I have found a variety of answers to similar questions stating that it is likely that the Windows Defender Firewall is blocking the port that is being used. For testing purposes, I tried disabling the firewall entirely for private networks such as the one that I am on. This didn't change anything, unfortunately.
I feel like I am missing something obvious and any input would be greatly appreciated.
Cheers!
StreamReader.ReadToEnd() on a NetworkStream will only return once the "end" of the stream is reached, which doesn't happen in your example; thus, the StreamReader times out.
You should fix this by using the lower-level NetworkStream.Read method to read from the stream:
var buffer = new byte[4096];
var bytesRead = stream.Read(buffer, 0, buffer.Length);
Console.WriteLine("Read {0} bytes", bytesRead);
string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine(response);
To make this test program more robust, you will also need to introduce "framing", i.e., some way for the server to indicate to the client that it can stop reading. This can be a terminator suffix, such as \r\n used by HTTP, or a length prefix that is sent upfront to tell the client how many more bytes to read.

C# tcp async listener gets stuck on my on_receive callback after client closes socket

I've got a listener socket that accepts, receives and sends as a TCP server typically does. I've given my accept and receive code below, it's not that different from the example on Microsoft's documentation. The main difference is that my server doesn't kill a connection after it stops receiving data (I don't know if this is a bad design or not?).
private void on_accept(IAsyncResult xResult)
{
Socket listener = null;
Socket handler = null;
TStateObject state = null;
Task<int> consumer = null;
try
{
mxResetEvent.Set();
listener = (Socket)xResult.AsyncState;
handler = listener.EndAccept(xResult);
state = new TStateObject()
{
Socket = handler
};
consumer = async_input_consumer(state);
OnConnect?.Invoke(this, handler);
handler.BeginReceive(state.Buffer, 0, TStateObject.BufferSize, 0, new AsyncCallback(on_receive), state);
}
catch (SocketException se)
{
if (se.ErrorCode == 10054)
{
on_disconnect(state);
}
}
catch (ObjectDisposedException)
{
return;
}
catch (Exception ex)
{
System.Console.WriteLine("Exception in TCPServer::AcceptCallback, exception: " + ex.Message);
}
}
private void on_receive(IAsyncResult xResult)
{
Socket handler = null;
TStateObject state = null;
try
{
state = xResult.AsyncState as TStateObject;
handler = state.Socket;
int bytesRead = handler.EndReceive(xResult);
UInt16 id = TClientRegistry.GetIdBySocket(handler);
TContext context = TClientRegistry.GetContext(id);
if (bytesRead > 0)
{
var buffer_data = new byte[bytesRead];
Array.Copy(state.Buffer, buffer_data, bytesRead);
state.BufferBlock.Post(buffer_data);
}
Array.Clear(state.Buffer, 0, state.Buffer.Length);
handler.BeginReceive(state.Buffer, 0, TStateObject.BufferSize, 0, new AsyncCallback(on_receive), state);
}
catch (SocketException se)
{
if(se.ErrorCode == 10054)
{
on_disconnect(state);
}
}
catch (ObjectDisposedException)
{
return;
}
catch (Exception ex)
{
System.Console.WriteLine("Exception in TCPServer::ReadCallback, exception: " + ex.Message);
}
}
This code is used to connect to an embedded device and works (mostly) fine. I was investigating a memory leak and trying to speed up the process a bit by replicating exactly what the device does (our connection speeds are in the realm of about 70kbps to our device, and it took an entire weekend of stress testing to get the memory leak to double the memory footprint of the server).
So I wrote a C# program to replicate the data transactions, but I've run into an issue where when I disconnect the test program, the server gets caught in a loop where it endlessly has its on_receive callback called. I was under the impression that BeginReceive wouldn't be triggered until something was received, and it seems to call on_receive, ends the receiving like an async callback should do, process the data, and then I want the connection to await more data so I call BeginReceive again.
The part of my test program where the issue occurs is in here:
private static void read_write_test()
{
mxConnection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mxConnection.Connect("12.12.12.18", 10);
if (mxConnection.Connected)
{
byte[] data = Encoding.ASCII.GetBytes("HANDSHAKESTRING"); //Connect string
int len = data.Length;
mxConnection.Send(data);
data = new byte[4];
len = mxConnection.Receive(data);
if (len == 0 || data[0] != '1')
{
mxConnection.Disconnect(false);
return;
}
}
//Meat of the test goes here but isn't relevant
mxConnection.Shutdown(SocketShutdown.Both);
mxConnection.Close();
}
Up until the Shutdown(SocketShutdown.Both) call, everything works as expected. When I make that call however, it seems like the server never gets notification that the client has closed the socket and gets stuck in a loop of endlessly trying to receive. I've done my homework and I think I am closing my connection properly as per this discussion. I've messed around with the disconnect section to just do mxConnection.Disconnect(false) as well, but the same thing occurs.
When the device disconnects from the server, my server catches a SocketException with error code 10054, which documentation says:
Connection reset by peer.
An existing connection was forcibly closed
by the remote host. This normally results if the peer application on
the remote host is suddenly stopped, the host is rebooted, the host or
remote network interface is disabled, or the remote host uses a hard
close (see setsockopt for more information on the SO_LINGER option on
the remote socket). This error may also result if a connection was
broken due to keep-alive activity detecting a failure while one or
more operations are in progress. Operations that were in progress fail
with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
I've used this to handle the socket being closed and has worked well for the most part. However, with my C# test program, it doesn't seem like it works the same way.
Am I missing something here? I'd appreciate any input. Thanks.
The main difference is that my server doesn't kill a connection after it stops receiving data (I don't know if this is a bad design or not?).
Of course it is.
it seems like the server never gets notification that the client has closed the socket and gets stuck in a loop of endlessly trying to receive
The server does get notification. It's just that you ignore it. The notification is that your receive operation returns 0. When that happens, you just call BeginReceive() again. Which starts a new read operation. Which…returns 0! You just keep doing that over and over again.
When a receive operation returns 0, you're supposed to complete the graceful closure (with a call to Shutdown() and Close()) that the remote endpoint started. Do not try to receive again. You'll just keep getting the same result.
I strongly recommend you do more homework. A good place to start would be the Winsock Programmer's FAQ. It is a fairly old resource and doesn't address .NET at all. But for the most part, the things that novice network programmers are getting wrong in .NET are the same things that novice Winsock programmers were getting wrong twenty years ago. The document is still just as relevant today as it was then.
By the way, your client-side code has some issues as well. First, when the Connect() method returns successfully, the socket is connected. You don't have to check the Connected property (and in fact, should never have to check that property). Second, the Disconnect() method doesn't do anything useful. It's used when you want to re-use the underlying socket handle, but you should be disposing the Socket object here. Just use Shutdown() and Close(), per the usual socket API idioms. Third, any code that receives from a TCP socket must do that in a loop, and make use of the received byte-count value to determine what data has been read and whether enough has been read to do anything useful. TCP can return any positive number of bytes on a successful read, and it's your program's job to identify the start and end of any particular blocks of data that were sent.
You missed this in the documentation for EndReceive() and Receive():
If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the Receive method will complete immediately and return zero bytes.
When you read zero bytes, you still start another BeginReceive(), instead of shutting down:
if (bytesRead > 0)
{
var buffer_data = new byte[bytesRead];
Array.Copy(state.Buffer, buffer_data, bytesRead);
state.BufferBlock.Post(buffer_data);
}
Array.Clear(state.Buffer, 0, state.Buffer.Length);
handler.BeginReceive(state.Buffer, 0, TStateObject.BufferSize, 0, new AsyncCallback(on_receive), state);
Since you keep calling BeginReceive on a socket that's 'shutdown', you're going to keep getting callbacks to receive zero bytes.
Compare with the example from Microsoft in the documentation for EndReceive():
public static void Read_Callback(IAsyncResult ar){
StateObject so = (StateObject) ar.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(ar);
if (read > 0) {
so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
new AsyncCallback(Async_Send_Receive.Read_Callback), so);
}
else{
if (so.sb.Length > 1) {
//All of the data has been read, so displays it to the console
string strContent;
strContent = so.sb.ToString();
Console.WriteLine(String.Format("Read {0} byte from socket" +
"data = {1} ", strContent.Length, strContent));
}
s.Close();
}
}

TCP Socket/NetworkStream Unexpectedly Failing

This specifically is a question on what is going on in the background communications of NetworkStream consuming raw data over TCP. The TcpClient connection is communicating directly with a hardware device on the network. Every so often, at random times, the NetworkStream appears to hiccup, and can be best described while observing in debug mode. I have a read timeout set on the stream and when everything is working as expected, when stepping over Stream.Read, it will sit there and wait the length of the timeout period for incoming data. When not, only a small portion of the data comes through, the TcpClient still shows as open and connected, but Stream.Read no longer waits for the timeout period for incoming data. It immediately steps over to the next line, no data is received obviously, and no data will ever come through until everything is disposed of and a new connection is reestablished.
The question is, in this specific scenario, what state is the NetworkStream in at this point, what causes it, and why is the TcpClient connection still in a seemingly open and valid state? What is going on in the background? No errors thrown and captured, is the stream silently failing in the background? What is the difference between states of TcpClient and NetworkStream?
private TcpClient Client;
private NetworkStream Stream;
Client = new TcpClient();
var result = Client.BeginConnect(IPAddress, Port, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2));
Client.EndConnect(result);
Stream = Client.GetStream();
try
{
while (Client.Connected)
{
bool flag = true;
StringBuilder sb = new StringBuilder();
while (!IsCompleteRecord(sb.ToString()) && Client.Connected)
{
string response = "";
byte[] data = new byte[512];
Stream.ReadTimeout = 60000;
try
{
int recv = Stream.Read(data, 0, data.Length);
response = Encoding.ASCII.GetString(data, 0, recv);
}
catch (Exception ex)
{
}
sb.Append(response);
}
string rec = sb.ToString();
// send off data
Stream.Flush();
}
}
catch (Exception ex)
{
}
You are not properly testing for the peer closing its end of the connection.
From this link : https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns 0. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.
You are simply doing a stream.read, and not interpreting the fact that you might have received 0 bytes, which means that the peer closed its end of the connection. This is called a half close. It will not send to you anymore. At that point you should also close your end of the socket.
There is an example available here :
https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
} else {
// All the data has arrived; put it in response.
if (state.sb.Length > 1) {
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set(); ---> not that this event is set here
}
and in the main code block it is waiting for receiveDone:
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
Conclusion : check for reception of 0 bytes and close your end of the socket because that is what the other end has done.
A timeout is handled with an exception. You are not really doing anything with a timeout because your catch block is empty. You would just continue trying to receive.
#Philip has already answered ythe question.
I just want to add that I recommend the use of SysInternals TcpView, which is basically a GUI for netstat and lets you easily check the status of all network connections of your computer.
About the detection of the connection state in your program, see here in SO.

TcpClient established, but TcpClient.getStream() fails

My Client class for synchronous message exchange:
public class AsClient
{
private TcpClient connection;
public AsClient(int serverPort, String ip)
{
connection = new TcpClient(ip, port);
}
public AsMessage sendMessage(AsMessage message)
{
System.Diagnostics.Debug.WriteLine("Connected: " + connection.Connected);
NetworkStream ns = connection.GetStream();
StreamReader reader = new StreamReader(ns);
StreamWriter writer = new StreamWriter(ns);
// Send Message:
String msgToSendEncoded = message.encode();
writer.WriteLine(msgToSendEncoded);
writer.WriteLine("\n"); // each message is terminated by a paragraph
writer.Flush();
// Receive Message:
String msgReceivedRaw = reader.ReadLine();
AsMessage response = AsMessage.decode(msgReceivedRaw);
reader.Dispose();
writer.Dispose();
ns.Close();
return response;
}
}
If I debug this application, the first message sent and response received works perfectly well, but as soon as I want to send the second message, TcpClient.getStream() fails with the InvalidOperationException, which states that the connection is not established anymore.
The problem is that I am not actively closing the connection anywhere. If I put connection.Connect(host,port) before calling getStream(), it fails with the exception that the socket is still connected, even though connection.Connected is false.
Any ideas to solve this issue?
As I have experience Dispose close the underlying stream.
So you close the connection on the Dispose.
I'm running into the same problem with this piece of code that replicates follows the steps in the MS documentation for GetStream(): https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.getstream?view=netframework-4.8
public void Send(String message)
{
try
{
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
NetworkStream stream = Client.GetStream();
stream.Write(data, 0, data.Length);
stream.Close(); // this also closses the connection the server!
}
catch (Exception e)
{
LogException(e);
}
}
What we see on the server side is that:
1) The connection is established.
2) The message never arrives.
3) when the stream.Close() statement executes, the server reports that the client closed the connection.
Inspecting the properties of stream I can see that streams OWNS the socket. So, wen it closes it must also close its socket. How come???

NetworkStream throws exception on Read() when client shuts down

I'm having some problems with an app i created. The general situation (the following description is not 1-1 related to question): I have a WCF client-server app for collecting data at multiple sites. The client retrieves local data (some files etc), sends it to the server in the datacenter and this server processes it. The client gets most of its data from the localhost, but some of it is retrieved from different servers on the LAN. Here's where my problem starts. I had to create a 3rd app which sends data to the stated client. In the reminder of this post i refer to client and server as the to apps on the same LAN (so not the server in the datacenter above)
I tried using named pipes, which went superb interprocess on the same host, but was immense slow server-to-server. (if anyone has thoughts on why this is plz dont hesitate to tell me. Some tests went up to 1000 ms sending and receiving just a few bytes)
So i went to using the TcpClient class. Tests showed responses much faster than the NP equivalents, so i decided to go with this option.
Now, when client and server start and end both as they are supposed to do, everything is fine. The problem arrises when the server is fired up, the client has connected, server is waiting its stream.Read() method, and then the client app exits:
Unable to read data from the transport connection: De externe host heeft een verbinding verbroken. (2nd part translation: An existing connection was forcibly closed by the remote host.)
At the moment i wrapped the whole part with a Try-Catch statement, restarting the whole thing on a IoException. This does work, but as i read several posts on "An exception should be something exceptional!", it does not feel well.
So finally the question: How can this exception been avoided?
(What is the normal way to keep a connection between server and client app in real life?)
Server
TcpListener serverSocket = new TcpListener(System.Net.IPAddress.Any, 8888);
TcpClient clientSocket = default(TcpClient);
while (true)
{
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
while ((true))
{
try
{
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);//THIS THROWS THE EXCEPTION WHEN A CLIENT QUITS
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Server response " + DateTime.Now.ToString("HH:mm:ss,fff");
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
int len = sendBytes.Length;
networkStream.WriteByte((byte)(len / 256));
networkStream.WriteByte((byte)(len & 255));
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
catch (System.IO.IOException ex)
{
Console.WriteLine(ex.ToString());
break;
}
}
clientSocket.Close();
serverSocket.Stop();
}
}
client
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
private void button2_Click(object sender, EventArgs e)
{
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("Message from Client$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
int len = serverStream.ReadByte() * 256;
len += serverStream.ReadByte();
byte[] inStream = new byte[len];
serverStream.Read(inStream, 0, len);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
msg("Data from Server : " + returndata);
}
private void button1_Click_1(object sender, EventArgs e)
{
clientSocket.Connect("127.0.0.1", 8888);
}
My understanding of the Socket API is that you are supposed to call Shutdown(Write) when you are done sending. Then, read until the stream returns 0. This means that the other side has called Shutdown, too.
Only after you have closed writing (using Shutdown) and received a zero-length read, the communication is really done on the wire. Now Dispose the Socket as it is now defunct.
That way you only get an exception if a network error or a bug occurred. In that case you should probably discard the current "transaction" and restart it.
This error has several causes, butt the most common is that you wrote to a connection that had already been closed by the other end. In other words, an application protocol error: you wrote something in a situation where it could never be consumed.
Another somewhat remote possibility if you wrote both ends is that you coded the client to close abortively for some reason. Basically you should never do that.

Categories

Resources