Here is my server:
class Server
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 5004);
listener.Start();
TcpClient client;
while (true)
{
client = listener.AcceptTcpClient();
if (client.Connected)
{
Console.WriteLine("client connected");
break;
}
}
NetworkStream sr = client.GetStream();
while (true)
{
byte[] message = new byte[1024];
sr.Read(message, 0, message.Length);
sr.Close();
Console.WriteLine(message.ToString());
}
}
}
and here is my client:
class Program
{
static void Main(string[] args)
{
TcpClient client = new TcpClient();
Console.WriteLine("Insert server address");
string server = Console.ReadLine();
if (server == "")
{
server = "192.168.1.2";
}
client.Connect(IPAddress.Parse(server), 5004);
NetworkStream sw = client.GetStream();
while (true)
{
byte[] message = Encoding.ASCII.GetBytes(Console.ReadLine());
sw.Write(message, 0, message.Length);
sw.Close();
}
}
}
When I run my server and the client first everything works and a "client connected" message appears. The problem is when I am trying to send a message from client to the server, a System.ObjectDisposedException is raised at the server in the sr.Read(message, 0, message.Length); line. Any idea how can I solved it or what is the cause?
You are closing the stream in the while loop, for both client and server. Move the Close below outside of the loop, or better still, make use of fact that Close calls Dispose, which allows you to use the IDisposable interface features like using:
using (NetworkStream sw = client.GetStream())
{
while (true)
{
byte[] message = Encoding.ASCII.GetBytes(Console.ReadLine());
sw.Write(message, 0, message.Length);
// Todo : Implement some kind of termination to the loop
}
sw.Flush();
}
Related
I want to create a .NET Core TCP server listening for incoming messages. I created a small class for testing purposes:
internal class TCPServer
{
private readonly TcpListener tcpListener;
public TCPServer()
{
tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
}
public async Task Start()
{
tcpListener.Start();
while (true)
{
TcpClient tcpClient = await tcpListener.AcceptTcpClientAsync();
NetworkStream networkStream = tcpClient.GetStream();
byte[] messageBuffer = new byte[tcpClient.ReceiveBufferSize];
int bytesRead = networkStream.Read(messageBuffer, 0, tcpClient.ReceiveBufferSize);
string dataReceived = Encoding.ASCII.GetString(messageBuffer, 0, bytesRead);
Console.WriteLine("Message from tcp client: " + dataReceived);
}
}
}
When sending messages to that listener the client itself runs into a timeout. As you can see here
I tried to solve it by adding this line
tcpClient.Close();
but then I get this error
How can I send messages to that server without getting an error?
How do you start your test server? Have you checked the port 1234 is opened? I would recommend checking it via "telnet 127.0.0.1 1234"
If YES could you share the client's code?
If NO could you share the code starting your server?
I've tried to run it via the code above and it works pretty well to me with the telnet tool as a client
class Program
{
static void Main(string[] args)
{
TCPServer server = new TCPServer();
Console.WriteLine("Starting...");
server.Start();
Console.WriteLine("Done.");
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
}
internal class TCPServer
{
private readonly TcpListener tcpListener;
public TCPServer()
{
tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
}
public async Task Start()
{
tcpListener.Start();
try
{
while (true)
{
TcpClient tcpClient = await tcpListener.AcceptTcpClientAsync();
NetworkStream networkStream = tcpClient.GetStream();
byte[] messageBuffer = new byte[tcpClient.ReceiveBufferSize];
int bytesRead = networkStream.Read(messageBuffer, 0, tcpClient.ReceiveBufferSize);
string dataReceived = Encoding.ASCII.GetString(messageBuffer, 0, bytesRead);
Console.WriteLine("Message from tcp client: " + dataReceived);
}
}
finally
{
tcpListener.Stop();
}
}
}
The problem is that you dispose of the client socket on your loop. Once you establish a client socket, you need to keep that socket alive.
This isn't proper "server" code, but it will show you what I mean and fix your issue:
while (true)
{
var tcpClient = await tcpListener.AcceptTcpClientAsync();
while(true){
var messageBuffer = new byte[4096];
Console.WriteLine("Waiting for data...");
int bytesRead;
try
{
bytesRead = tcpClient.GetStream().Read(messageBuffer, 0, messageBuffer.Length);
}catch{ break; } // disconnected
var dataReceived = Encoding.ASCII.GetString(messageBuffer, 0, bytesRead);
Console.WriteLine($"Message from tcp client ({bytesRead} bytes): {dataReceived}");
}
}
This solution will make this work, but you can't have more than one client connected to your server at the same time. In order to do that, you need to use TPL, or worst case, create a thread for each client.
Take a look at BeginRead/EndRead to see what I mean.
I am setting up a server to read some network clients using TcpListener. The Client sends some data I verify that data and send a response to that data, the client stays connected and sends a second response and I verify that data and send a response back, its like logging in to the server twice. The first login get sent back to the client just fine but the second time the client responds the server does not show that it received anymore data from the client.
I have tested it by setting up a dummy client (the real client is Cell phone based ODB2). With the dummy client set up I did verify that the first handshake happens but the when the client sends the second set of text it does not show up on the server.
class Program
{
static private TcpListener listener = null;
static private TcpClient client = null;
static private NetworkStream stream = null;
static private int iCount = 0;
static Int32 port = 8090;
static IPAddress localAddr = IPAddress.Parse("192.168.1.17");
static void Main(string[] args)
{
listener = new TcpListener(localAddr, port);
listener.Start();
while (true)
{
try
{
client = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(ThreadProc, client);
}
catch (IOException ioex)
{
RestartStream();
}
}
}
private static void ThreadProc(object obj)
{
var client = (TcpClient)obj;
Byte[] bytes = new Byte[client.ReceiveBufferSize];
stream = client.GetStream();
try
{
int bytesRead = stream.Read(bytes, 0, (int)client.ReceiveBufferSize);
string returndata = Encoding.ASCII.GetString(bytes, 0, bytesRead).Replace("-", "");
byte[] sendBytes;
if (returndata.ToLower().StartsWith("7e") && returndata.ToLower().EndsWith("7e"))
{
//… do stuff with the data and send it back to the client
sendBytes = Encoding.Default.GetBytes(login1);
stream.Write(sendBytes, 0, sendBytes.Length);
stream.Flush();
}
else
{
SaveStream(returndata);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Test Client Code:
//---data to send to the server---
string textToSend = "7E010000360141850000080000000000000000000000000000000000000000000000000000000000000035303030303038003131313131313131313131313131313131F67E";
//---create a TCPClient object at the IP and port no.---
TcpClient client = new TcpClient(SERVER_IP, PORT_NO);
NetworkStream nwStream = client.GetStream();
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(textToSend);
//---send the text---
Console.WriteLine("Sending : " + textToSend);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
//---read back the text---
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));
string Text2 = "7E0100003601418535303030303038003131313131313131313131313131313131F67E";
Console.WriteLine("Sending : " + Text2);
byte[] bytesToSend2 = ASCIIEncoding.ASCII.GetBytes(Text2);
nwStream.Write(bytesToSend2, 0, bytesToSend2.Length);
client.Close();
Console.ReadLine();
What I need to happen is my understanding is the client stays connected the whole time and send data over and over, my system seems to accept it once and then stops receiving it, I need it to continue to receive the client data and process it.
Ok so I figured it out, there should be a second while loop in side the thread.
static void Main(string[] args)
{
listener = new TcpListener(localAddr, port);
var clientSocket = default(TcpClient);
listener.Start();
var counter = 0;
while (true)
{
clientSocket = listener.AcceptTcpClient();
var client = new ConnectedDevice();
client.startClient(clientSocket, counter.ToString(), sqlConnString);
}
}
ConnectedDevice class:
class ConnectedDevice
{
private TcpClient _clientSocket;
private string _clientNumber;
private string _sqlConnString;
public void startClient(TcpClient clientSocket, string clientNumber, string sqlConnString)
{
_clientSocket = clientSocket;
_clientNumber = clientNumber;
_sqlConnString = sqlConnString;
var ctThread = new Thread(ProcessClient);
ctThread.Start();
}
private void ProcessClient()
{
while (_clientSocket.Connected)
{
try
{
Byte[] bytes = new Byte[_clientSocket.ReceiveBufferSize];
var networkStream = _clientSocket.GetStream();
networkStream.ReadTimeout = 10000;
int i;
while ((i = networkStream.Read(bytes, 0, bytes.Length)) != 0)
{
var data = System.Text.Encoding.ASCII.GetString(bytes, 0, i).Replace("-", "");
byte[] sendBytes;
Console.WriteLine(data);
string sLogin1 = "7E81000013014185000008000000000054523230313731303138303930303137497E";
sendBytes = Encoding.ASCII.GetBytes(sLogin1);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
}
catch (Exception ex)
{
}
}
}
}
The below code is Microsoft's code sample for TcpListener but I can't run that:
using System;
using System.Net;
using System.Net.Sockets;
public class TcpListenerSample
{
static void Main(string[] args)
{
try
{
// set the TcpListener on port 13000
int port = 13000;
TcpListener server = new TcpListener(IPAddress.Any, port);
// Start listening for client requests
server.Start();
// Buffer for reading data
byte[] bytes = new byte[1024];
string data;
//Enter the listening loop
while (true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
i = stream.Read(bytes, 0, bytes.Length);
while (i != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(String.Format("Received: {0}", data));
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine(String.Format("Sent: {0}", data));
i = stream.Read(bytes, 0, bytes.Length);
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("Hit enter to continue...");
Console.Read();
}
}
The code is stay into the loop in this line:
TcpClient client = server.AcceptTcpClient();
I've turned the firewall off but nothing changed.
How can I solve this?
AcceptTcpClient() is a blocking call which will block until a client has connected to your TcpListener. Therefore you need to use some kind of client application to test your server and connect to it. You could use Putty for this.
I have two basic console apps that communicate "over the network" even though all of the communication takes place on my local machine.
Client code:
public static void Main()
{
while (true)
{
try
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 500);
Console.WriteLine("Connected.");
byte[] data = ASCIIEncoding.ASCII.GetBytes(new FeederRequest("test", TableType.Event).GetXmlRequest().ToString());
Console.WriteLine("Sending data.....");
using (var stream = client.GetStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Data sent.");
}
client.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
}
Server code:
public static void Main()
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 500);
listener.Start();
Console.WriteLine("Server is listening on " + listener.LocalEndpoint);
while (true)
{
Socket client = listener.AcceptSocket();
Console.WriteLine("\nConnection accepted.");
var childSocketThread = new Thread(() =>
{
Console.WriteLine("Reading data...\n");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("Recieved data: ");
for (int i = 0; i < size; i++)
Console.Write(Convert.ToChar(data[i]));
//respond to client
Console.WriteLine("\n");
client.Close();
Console.WriteLine("Waiting for a connection...");
});
childSocketThread.Start();
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
How can I alter both of these applications so that when the Server has received the data, it responds to the Client with some kind of confirmation?
Thanks in advance!
Here a short example how I would do it:
Server:
class Server
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 1500);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
// Create BinaryWriter for writing to stream
BinaryWriter binaryWriter = new BinaryWriter(stream);
// Creating BinaryReader for reading the stream
BinaryReader binaryReader = new BinaryReader(stream);
while (true)
{
// Read incoming information
byte[] data = new byte[16];
int receivedDataLength = binaryReader.Read(data, 0, data.Length);
string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
// Write incoming information to console
Console.WriteLine("Client: " + stringData);
// Respond to client
byte[] respondData = Encoding.ASCII.GetBytes("respond");
Array.Resize(ref respondData, 16); // Resizing to 16 byte, because in this example all messages have 16 byte to make it easier to understand.
binaryWriter.Write(respondData, 0, 16);
}
}
}
Client:
class Client
{
private static void Main(string[] args)
{
Console.WriteLine("Press any key to start Client");
while (! Console.KeyAvailable)
{
}
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 1500);
NetworkStream networkStream = client.GetStream();
// Create BinaryWriter for writing to stream
BinaryWriter binaryWriter = new BinaryWriter(networkStream);
// Creating BinaryReader for reading the stream
BinaryReader binaryReader = new BinaryReader(networkStream);
// Writing "test" to stream
byte[] writeData = Encoding.ASCII.GetBytes("test");
Array.Resize(ref writeData, 16); // Resizing to 16 byte, because in this example all messages have 16 byte to make it easier to understand.
binaryWriter.Write(writeData, 0, 16);
// Reading response and writing it to console
byte[] responeBytes = new byte[16];
binaryReader.Read(responeBytes, 0, 16);
string response = Encoding.ASCII.GetString(responeBytes);
Console.WriteLine("Server: " + response);
while (true)
{
}
}
}
I hope this helps! ;)
You can perform both Read and Write on the same stream.
After you send all the data over, just call stream.Read as in
using (var stream = client.GetStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Data sent.");
stream.Read(....); //added sync read here
}
MSDN documentation on TcpClient has an example as well http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx
If you want feed back such as reporting # of bytes received so far, you'll have to use async methods.
Here's an example of what (I think) you want to do:
static void Main(string[] args) {
var server = new Task(Server);
server.Start();
System.Threading.Thread.Sleep(10); // give server thread a chance to setup
try {
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 1500);
Console.WriteLine("Connected.");
var data = new byte[100];
var hello = ASCIIEncoding.ASCII.GetBytes("Hello");
Console.WriteLine("Sending data.....");
using (var stream = client.GetStream()) {
stream.Write(hello, 0, hello.Length);
stream.Flush();
Console.WriteLine("Data sent.");
// You could then read data from server here:
var returned = stream.Read(data, 0, data.Length);
var rec = new String(ASCIIEncoding.ASCII.GetChars(data, 0, data.Length));
rec = rec.TrimEnd('\0');
if (rec == "How are you?") {
var fine = ASCIIEncoding.ASCII.GetBytes("fine and you?");
stream.Write(fine, 0, fine.Length);
}
}
client.Close();
Console.ReadLine();
}
catch (Exception e) {
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
public static void Server() {
try {
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("*Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 1500); // generally use ports > 1024
listener.Start();
Console.WriteLine("*Server is listening on " + listener.LocalEndpoint);
Console.WriteLine("*Waiting for a connection...");
while (true) {
Socket client = listener.AcceptSocket();
while (client.Connected) {
Console.WriteLine("*Connection accepted.");
Console.WriteLine("*Reading data...");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("*Recieved data: ");
var rec = new String(ASCIIEncoding.ASCII.GetChars(data, 0, size));
rec = rec.TrimEnd('\0');
Console.WriteLine(rec);
if (client.Connected == false) {
client.Close();
break;
}
// you would write something back to the client here
if (rec == "Hello") {
client.Send(ASCIIEncoding.ASCII.GetBytes("How are you?"));
}
if (rec == "fine and you?") {
client.Disconnect(false);
}
}
}
listener.Stop();
}
catch (Exception e) {
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
}
Keep in mind that data sent via sockets can arrive fragmented (in different packets). This doesn't usually happen with the packets are small.
I'm running a TCP server in c#. The program seems to run and hold for new clients (it stop on TcpClient client = this.tcpListener.AcceptTcpClient();) waiting for new connections. However if I check the network (using the netstat command) the server is not listening, wich means is not running. I also tryied with different ports, but I guess than port 80 should be good for testing (I also tried with other ports and none of them worked). What is wrong in my code? Maybe the OS is blocking the server?
namespace TCPServer
{
class TestClass
{
static void Main(string[] args)
{
Server TCPServer = new Server();
// Display the number of command line arguments:
System.Console.WriteLine(args.Length);
}
}
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 80);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
System.Console.WriteLine("Server started");
}
//starts the tcp listener and accept connections
private void ListenForClients()
{
this.tcpListener.Start();
System.Console.WriteLine("Listener started");
while (true)
{
System.Console.WriteLine("Accepting Clients");
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
System.Console.WriteLine("Client connected");
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
//Read the data from the client
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client; //start the client
NetworkStream clientStream = tcpClient.GetStream(); //get the stream of data for network access
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0) //if we receive 0 bytes
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
//Reply
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
tcpClient.Close();
}
}
}
Update:
I configure the app to get a firewall exemption. Im running in windows7. I also checked with the port 3000 and nothing listening on that port. I use the netstat output to determine if its listening or not.