Displaying a string array on client console sent from server in c# - c#

Here is a sample server and client code in c#. The server will send an array of string and the client will receive it and display and then the client will send an id and the server will receive it and display. But I am getting an exception in my the server while running both of them.
The exception is as follows:
An unhandled exception of type 'System.ObjectDisposedException' occurred in System.dll
Additional information: Cannot access a disposed object.
Client:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace Client
{
class Program
{
static void Main(string[] args)
{
try
{
byte[] data = new byte[1024];
string stringData;
TcpClient tcpClient = new TcpClient("127.0.0.1", 1234);
NetworkStream ns = tcpClient.GetStream();
var serializer = new XmlSerializer(typeof(string[]));
var stringArr = (string[])serializer.Deserialize(tcpClient.GetStream());
foreach (string s in stringArr)
{
Console.WriteLine(s);
}
string input = Console.ReadLine();
ns.Write(Encoding.ASCII.GetBytes(input), 0, input.Length);
ns.Flush();
}
catch (Exception e)
{
Console.Write(e.Message);
}
Console.Read();
}
}
}
Server:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace server
{
class Program
{
static void Main(string[] args)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
byte[] data = new byte[1024];
NetworkStream ns = tcpClient.GetStream();
string[] arr1 = new string[] { "one", "two", "three" };
var serializer = new XmlSerializer(typeof(string[]));
serializer.Serialize(tcpClient.GetStream(), arr1);
tcpClient.Close();
int recv = ns.Read(data, 0, data.Length); //getting exception in this line
string id = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(id);
}
}
}
}
Is there anything wrong?
What will I need to change to avoid this exception?

Once you call
tcpClient.Close();
it cleans up resources associated with it, including disposing ns.
The following line
int recv = ns.Read(data, 0, data.Length); //getting exception in this line
attempts to read from ns after you just (indirectly) disposed of it.
Do not close the connection until you are done with it. Also, use the using keyword instead of explicitly closing the connection, as it will ensure proper cleanup even if an exception is thrown.

Related

How can I make a server print a notification as soon as a client connects to it?

Take a look at the following two programs:
//Server
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MyServerProgram
{
class Program
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 2000;
TcpListener listener = new TcpListener(ip, port);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream netStream = client.GetStream();
BinaryReader br = new BinaryReader(netStream);
try
{
while (client.Client.Connected)
{
string str = br.ReadString();
Console.WriteLine(str);
}
}
catch
{
br.Close();
netStream.Close();
client.Close();
listener.Stop();
}
}
}
}
//Client
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MyClientProgram
{
class Program
{
static void Main(string[] args)
{
int port = 2000;
TcpClient client = new TcpClient("localhost", port);
NetworkStream netStream = client.GetStream();
BinaryWriter br = new BinaryWriter(netStream);
try
{
int i=1;
while (client.Client.Connected)
{
br.Write(i.ToString());
br.Flush();
i++;
int milliseconds = 2000;
System.Threading.Thread.Sleep(milliseconds);
}
}
catch
{
br.Close();
netStream.Close();
client.Close();
}
}
}
}
These programs are working fine.
Suppose, at this point of this program, I need the server to print a message on the screen as soon as a client gets connected to it, and, also when the client is disconnected.
How can I do that?
AcceptTcpClient blocks execution and starts waiting for connection. So right after it you can write message that client connected. Also you could write connected client address. Just for information, but sometimes it could be helpful.
TcpClient client = listener.AcceptTcpClient();
ShowMessage("Connected " + ((IPEndPoint)client.Client.RemoteEndPoint).Address);
For detect client disconnect you could catch exceptions. Change your catch like this:
catch (Exception ex) {
var inner = ex.InnerException as SocketException;
if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
ShowMessage("Disconnected");
else
ShowMessage(ex.Message);
...

Asynchronous tcp client in C# connecting to API... Sporadic errors

I am writing a TCP Client in C# that is meant to connect to a 3rd-party API server. The vendor is insisting the problem is our code. They have provided a sample TCP client .exe to test against their API. I am generally successful connecting to their API with their app and using Packet Sender. I cannot figure out the problem in my code, though, so I'm hoping I can get some help seeing where I'm going wrong.
I have to make an initial call to ensure a setting is correct, then I can make my API call. It seems as though the API call only returns results when I make my call asynchronously. I'll get successful results 2 or 3 times in a row, and then I'll get an error message that is indecipherable without access to the vendor's source code. I got this code from an MSDN sample or someplace else reputable, but I still seem to get an error from the API (it hangs up and stops responding until I restart it) every 5th call or so (it's inconsistent when I get the error). Can someone help me debug my code? I'm genericizing it so that I'm not putting anything specific to the vendor's API here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace tcp
{
class AsyncClient
{
static void Main(string[] args)
{
SetInitialSetting();
ConnectAsTcpClient();
Console.ReadLine();
}
private static void SetInitialSetting()
{
byte[] data = new byte[1024];
string stringData;
IPAddress ip;
int port;
int recv;
IPAddress.TryParse(#"127.0.0.1", out ip);
port = 10000;
SetInitialSettingString();
Console.WriteLine("[Client] Writing request {0}", ClientRequestString);
using (var client = new TcpClient(ip.ToString(), port))
{
NetworkStream ns = client.GetStream();
ns.Write(ClientRequestBytes, 0, ClientRequestBytes.Length);
stringData = "";
do
{
recv = ns.Read(data, 0, data.Length);
stringData = stringData + Encoding.UTF8.GetString(data, 0, recv);
}
while (ns.DataAvailable);
Console.WriteLine("[Client] Server response was {0}", stringData);
ns.Close();
}
}
private static async void ConnectAsTcpClient()
{
byte[] data = new byte[10025];
IPAddress ip;
int port;
IPAddress.TryParse(#"127.0.0.1", out ip);
port = 10000;
using (var tcpClient = new TcpClient())
{
Console.WriteLine("[Client] Connecting to server");
await tcpClient.ConnectAsync(ip, port);
Console.WriteLine("[Client] Connected to server");
using (var networkStream = tcpClient.GetStream())
{
SetAPICallString();
Console.WriteLine("[Client] Writing request {0}", ClientRequestString);
await networkStream.WriteAsync(ClientRequestBytes, 0, ClientRequestBytes.Length);
var buffer = new byte[4096];
var byteCount = await networkStream.ReadAsync(buffer, 0, buffer.Length);
var response = Encoding.UTF8.GetString(buffer, 0, byteCount);
Console.WriteLine("[Client] Server response was {0}", response);
}
}
}
private static string ClientRequestString;
private static byte[] ClientRequestBytes;
private static void SetInitialSettingString()
{
ClientRequestString = "StringThatSetsTheAPISettingGoesHere";
ClientRequestBytes = Encoding.UTF8.GetBytes(ClientRequestString);
}
private static void SetAPICallString()
{
ClientRequestString = "StringForTheCallToTheAPIThatINeedGoesHere";
ClientRequestBytes = Encoding.UTF8.GetBytes(ClientRequestString);
}
}
}

I can't connect to test a local server started with TcpListener

Disclaimer: this is my first foray into anything directly tcp/socket related. I've read -the- -following- -resources- and am trying to come up with a very simple test application.
I'm trying to develop a local server running with a TcpListener object. I can instantiate it fine and run netstat to see the port in the LISTENING state. However, I can't telnet or create a test client to connect manually. Telnet says simply that it could not open a connection. Trying a test client application throws the exception
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: Only one usage of each socket address (protocol/network address/port) is normally permitted
In this SO question, the asker ultimately resolved it via a faulty NIC. How might I look for that?
This leaves me puzzled. How do I ever test or connect to the server? Here's my code.
For the server:
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace TcpConsole
{
class Program
{
static void Main(string[] args)
{
var localPort = ConfigurationManager.AppSettings["localPort"];
var portNumber = int.Parse(localPort);
var maxConnections = ConfigurationManager.AppSettings["maxConnections"];
var maxConnectionsNumber = int.Parse(maxConnections);
Console.WriteLine("Preparing to start server on port {0}", portNumber);
Console.WriteLine("Max connections: {0}", maxConnectionsNumber);
var ipHostInfo = Dns.GetHostEntry("localhost");
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, portNumber);
Console.WriteLine("Starting server with local IP {0}", ipAddress);
var listener = new TcpListener(localEndPoint);
listener.Start(maxConnectionsNumber);
Console.WriteLine();
Console.WriteLine("Server started...");
Console.WriteLine();
while (true)
{
var socket = listener.AcceptSocket();
Task.Factory.StartNew(() =>
{
ProcessSocket(socket);
});
}
}
private static async void ProcessSocket(Socket socket)
{
try
{
using (var stream = new NetworkStream(socket))
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
var received = await reader.ReadToEndAsync();
Console.WriteLine("Received: " + received);
}
socket.Close();
socket.Dispose();
}
catch (Exception exception)
{
Console.WriteLine("There was an error processing a message.");
Console.WriteLine(exception);
}
}
}
}
Seeing the above code running:
For the test application:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace TcpConsoleClient
{
class Program
{
static void Main(string[] args)
{
var ipHostInfo = Dns.GetHostEntry("localhost");
var ipAddress = ipHostInfo.AddressList[0];
var remoteEndPoint = new IPEndPoint(ipAddress, 3245);
var client = new TcpClient(remoteEndPoint);
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
string input;
while((input = Console.ReadLine()) != "exit")
{
writer.WriteLine(input);
}
}
}
}
}
A TCP/IP connection has a local IP address and port, as well as a remote IP address and port.
Generally, a port number can only be assigned to one socket at a time. The error message indicates that an attempt was made to associate more than one socket with the same port number.
The reason why can be found in the client code:
var client = new TcpClient(remoteEndPoint);
This overload of the TcpClient constructor accepts an IPEndPoint specifying the local endpoint. That is, when the TcpClient is constructed, it will get bound to the port number specified by remoteEndPoint, which fails, because that port number is already in use by the server application.
To fix this, use the parameter-less TcpClient constructor, and instead pass remoteEndPoint to the Connect call:
var client = new TcpClient();
client.Connect(remoteEndPoint);

Client send message server not received message in tcp/ip socket program

TCP/IP socket program client send text server receive and store database table. I'm righting code below but i have error text reeving time.
This is Client Side Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.IO;
namespace ClientApplication
{
class Client
{
static void Main(string[] args)
{
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
//tcpclnt.Connect("162.144.85.232", 8080);
tcpclnt.Connect("162.144.85.232", 4489);
Console.WriteLine("Connected");
Console.Write("Enter the string to be Sent : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
System.Net.ServicePointManager.Expect100Continue = false;
Console.WriteLine("Sending.....");
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
Console.ReadLine();
tcpclnt.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
Console.ReadLine();
}
}
}
}
This Is Server Side Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ServerApplication
{
class Server
{
static void Main(string[] args)
{
try
{
IPAddress ipadd = IPAddress.Parse("192.168.1.7");
TcpListener list = new TcpListener(ipadd, 8080);
list.Start();
Console.WriteLine("The server is running at port 8080...");
Console.WriteLine("The Local End point Is:" + list.LocalEndpoint);
System.Net.ServicePointManager.Expect100Continue = false;
Socket s = list.AcceptSocket();
Console.WriteLine("Connections Accepted from:" + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("Recived...");
for (int i = 0; i < k; i++)
Console.WriteLine(Convert.ToChar(b[i]));
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The String Was Recived throw Server"));
Console.WriteLine("\n Sent Acknowlegment");
s.Close();
list.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
I'm trying to execute this code i have error happen like this
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. Please resolve my issue .
There are a number of problems with the code you posted, but the one directly causing the behavior you're seeing is that the server closes the socket without waiting for the client to finish reading from the connection.
Look up "TCP graceful shutdown" for more information. In the meantime, the following is an improvement on the code you posted and won't have that problem:
Server code:
class Server
{
static void Main(string[] args)
{
try
{
TcpListener list = new TcpListener(IPAddress.Any, 8080);
list.Start();
Console.WriteLine("The server is running at port 8080...");
Console.WriteLine("The Local End point Is:" + list.LocalEndpoint);
Socket s = list.AcceptSocket();
Console.WriteLine("Connections Accepted from:" + s.RemoteEndPoint);
byte[] b = new byte[100];
int k;
while ((k = s.Receive(b)) > 0)
{
Console.WriteLine("Recived...");
Console.WriteLine(Encoding.ASCII.GetString(b, 0, k));
s.Send(Encoding.ASCII.GetBytes("The String Was Recived throw Server"));
Console.WriteLine("\n Sent Acknowlegment");
}
s.Shutdown(SocketShutdown.Both);
s.Close();
list.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
Client code:
class Client
{
static void Main(string[] args)
{
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.168.1.7", 8080);
Console.WriteLine("Connected");
Console.Write("Enter the string to be Sent : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
byte[] ba = Encoding.ASCII.GetBytes(str);
Console.WriteLine("Sending.....");
stm.Write(ba, 0, ba.Length);
tcpclnt.Client.Shutdown(SocketShutdown.Send);
byte[] bb = new byte[100];
int k;
while ((k = stm.Read(bb, 0, 100)) > 0)
{
Console.WriteLine(Encoding.ASCII.GetString(bb, 0, k));
}
Console.ReadLine();
tcpclnt.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
Console.ReadLine();
}
}
}
The key thing here is that both server and client continue to read from the connection until the remote end has, by calling Socket.Shutdown(), signaled that there is no more data to be read.
I also removed the use of the System.Net.ServicePointManager.Expect100Continue property, which had no effect in this code. That only affects programs that use the ServicePoint class and is not useful here.
It's also not clear to me why for the client you use the NetworkStream instead of just getting the Client socket and using it directly. The NetworkStream object is useful when wrapping your I/O in e.g. StreamReader and StreamWriter, but here you're just using Stream.Read() and Stream.Write(), which have the exact same semantics as Socket.Receive() and Socket.Send(), respectively. In any case, note that while you are using the NetworkStream object for the send and receive, you still need to access the underlying Socket instance directly to correctly initiate the graceful shutdown (the endpoint not initiating could just close the NetworkStream, since it doesn't have to shutdown until it's done both sending and receiving).
I also cleaned up the handling of the ASCII-encoded text a bit.

Unable to read from stream in C#

I am building a bare bones program that simple delivers a message from server to client.
Now i am successfully able to establish connection between the server and client, however the client program is unable to read from the stream. Here's my code.
Code for server program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
namespace chat_client_console
{
class Program
{
static TcpListener listener;
static void Main(string[] args)
{
string name = Dns.GetHostName();
IPAddress[] address = Dns.GetHostAddresses(name);
/*
foreach(IPAddress addr in address)
{
Console.WriteLine(addr);
}*/
Console.WriteLine(address[1].ToString());
listener = new TcpListener(address[1], 2055);
listener.Start();
Socket soc = listener.AcceptSocket();
Console.WriteLine("Connection successful");
Stream s = new NetworkStream(soc);
StreamReader sr = new StreamReader(s);
StreamWriter sw = new StreamWriter(s);
sw.AutoFlush = true;
sw.Write("A test message");
Console.WriteLine("Test message delivered. Now ending the program");
/*
string name = Dns.GetHostName();
Console.WriteLine(name);
//IPHostEntry ip = Dns.GetHostEntry(name);
//Console.WriteLine(ip.AddressList[0].ToString());
IPAddress[] adr=Dns.GetHostAddresses(name);
foreach (IPAddress adress in adr)
{
Console.WriteLine(adress);
}
*/
Console.ReadLine();
}
}
}
and here's the code from the client program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
namespace chat_client_console_client
{
class Program
{
static void Main(string[] args)
{
string display;
TcpClient client = new TcpClient("localhost", 2055);
Stream s = client.GetStream();
Console.WriteLine("Connection successfully received");
StreamWriter sw = new StreamWriter(s);
StreamReader sr = new StreamReader(s);
sw.AutoFlush = true;
while (true)
{
display = sr.ReadLine();
Console.WriteLine("Reading stream");
if (display == "")
{
Console.WriteLine("breaking stream");
break;
}
}
Console.WriteLine(display);
}
}
}
now i am successfully able to establish connection between the programs as indicated by various check messages. The server program is also successfully able to send the data into the stream.
However the client program is unable to read data from the stream. It seems to be stuck at readline() function.
Now i have been banging my head against the wall on this problem for hours now and would be greatly thankful if somebody is able to help me.
Look at your server:
sw.AutoFlush = true;
sw.Write("A test message");
You're never writing a line break, which is what the client is waiting to see.

Categories