Waiting for data from server .net Tcp - c#

I have Tcp Client-Server application. Client write data to stream, and wait for data from server.
But server doing work near 10-15 seconds, so how would better for client to wait data from server? Put some "waiter" method in background thread or to sleep client for some time?
Client:
client.Connect(ip, serverPort);
Thread.Sleep(500);
using (NetworkStream stream = client.GetStream())
{
XmlSerializer xmlSerializer = new XmlSerializer(user.GetType());
xmlSerializer.Serialize(stream, user);
Thread.Sleep(250);
//WaitSignal(client);
}
Server:
TcpListener listener = new TcpListener(ip, serverPort);
string msg = "Hello;"
listener.Start();
while (true)
{
Console.WriteLine("Wait...");
TcpClient client = listener.AcceptTcpClient();
using (NetworkStream stream = client.GetStream())
{
//read bytes from stream and do some work
byte[] data = Encoding.ASCII.GetBytes(msg);
stream.Write(data, 0, data.Length);
}
}

Related

I have multiple TcpClient connections, how do I select a specific one?

I have a TCP Client
Log.Warn("Trying to connect to " + IP);
TcpClient client = new TcpClient(IP, Port);
string command = "";
while (!command.Contains("quit"))
{
Log.WriteSingle("localhost#", ConsoleColor.DarkYellow);
Log.WriteSingle(IP + ":", ConsoleColor.Yellow);
command = Console.ReadLine();
byte[] data = Encoding.ASCII.GetBytes(command);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
Log.Success("Sent command to network.");
// Buffer to store the response bytes.
data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Log.Write("Server Says: " + responseData, ConsoleColor.DarkYellow);
}
and a TCP Server
while(true)
{
Log.Write("Waiting for connection...");
TcpClient client = server.AcceptTcpClient();
Log.Success("Connected! ");
//Update list (Currently useless)
clientList.Add(client);
Thread t = new Thread(new ThreadStart(()=>ConnectClient(client,bytes,data)));
t.Start();
}
public static void ConnectClient(TcpClient _client, byte[] _bytes, string _data)
{
_data = null;
NetworkStream stream = _client.GetStream();
int i;
while((i = stream.Read(_bytes,0,_bytes.Length))!=0)
{
_data = System.Text.Encoding.ASCII.GetString(_bytes,0,i);
Log.Write("Recieved: "+_data, ConsoleColor.Cyan);
//Send back to client
_data = _data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(_data);
stream.Write(msg,0,msg.Length);
Log.Write("Sent: "+_data);
}
_client.Close();
}
I have it setup so the server listens to client connections and pop them off in a new thread once they connect. The client can send the server a string, and the server reflects it back.
I assume I can use a dictionary to assign an ID and store the client, or even just a simple List.
How would I structure it so I can add them to a List or a Dictionary and still be able to connect multiple clients?
Thanks
Put your accept() loop in a thread of its own. It can add to the list each time a new client connects.
Leave your main thread to manage all the client threads, including the accept() thread.

C# - Does TcpClient connection (& listening) use bandwith?

I wrote a small c# winform app that connects to my DSC alarm (via Envisalink4 by Eyez-On) and listens for TCP data sent by the alarm.
Here's an example of what I'm doing:
TcpClient tcpClient = new TcpClient(ipAddress, port);
Thread tcpThread = new Thread(o =>
{
NetworkStream clientStream = tcpClient.GetStream();
byte[] data = new byte[4096];
while (started)
{
int bytesRead = clientStream.Read(data, 0, 4096);
if (bytesRead > 0)
{
string dataString = Encoding.ASCII.GetString(responseData);
//DO SOMETHING
}
}
});
tcpThread.Start();
My question is - Other than when the alarm sends data, is any bandwidth being used while this code is waiting/listening for the server? Is there any "TCP connection overhead" while listening?
Thanks in advance!
You could use a sniffer like Wireshark to check your tcp connection

TcpListener doesn't accept TcpClient

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.

setting up a tcp server to communicate with android and kinect

I am making a dual app with android and kinect. I want to be able to send notifications to the android app from the kinect. I was told that the best way to accomplish this is to set up a simple tcp server. I tried to set it up by using the tutorial at this <link>. The tutorial however isn't descriptive enough for me and I am unable to make it work. The guy who posted it basically posted several pieces of code without any instruction about assembling them. I need someone to either walk me through setting up this server or I need a link to a detailed tutorial. I have searched the web myself for hours but I haven't found anything useful, which is why I'm asking here.
Here's what I thought he was saying to do in that tutorial:
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace TCPServerTutorial
{
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
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)
{
//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));
}
tcpClient.Close();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
//you'll have to find a way to pass this arg
private void SendBack(TcpClient tcpClient)
{
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
}
}
}
But that's just me. He only ever talked about one class, so it is logical to assume all his functions are in that class.
For the client code, he pretty much just gives you the code for a function (in C#, of course) which will send some bytes to an IP address (aka, the IP of the machine your server is running on). You could put this function in any C# class and call it in whatever way you wish. He has hard coded the IP address and the message to send, but these could easily be arguments passed to the function.
private void SendToServer(){
TcpClient client = new TcpClient();
//IP of the server: currently loopback, change to whatever you want
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
//Message being sent: "Hello Server!"
byte[] buffer = encoder.GetBytes("Hello Server!");
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
}

Send client side data Queue to server side through Tcp/IP

I wanna send data from client to server. There are two queues. in client side and in server side. I want to my client to be connected to the server and send all the data in client queue to the server. In server side I wanna accept all the clients and get all objects and add to the server side queue
Client code :
Queue<Person> clientQueue; // This is the client side queue
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 15884);
var client = new TcpClient();
while(!clientQueue.IsEmpty)
{
Person personObj = clientQueue.Dequeue();
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(clientStream, personObj);
clientStream.Flush();
}
Server Side :
Queue<Person> serverQueue; // This is the server side queue
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 15884);
TcpListener tcpListener = new TcpListener(ipEndPoint);
while(true)
{
TcpClient client = tcpListener.AcceptTcpClient();
NetworkStream clientStream = tcpClient.GetStream();
BinaryFormatter bf = new BinaryFormatter();
Person person = (Person)bf.Deserialize(clientStream);
tcpClient.Close();
serverQueue.Enqueue(person);
}
I know above code is not working. I just wanna sketch my design. Can someone please send me the code example. How to send client queue to server queue..
Thanks..
For the queue at both the server and the client side you should use BlockingCollection if you are using .net 4.0, for earlier versions use a combination of Queue and AutoResetEvent. check this.
At server side you should use asynchronous methods or just instantiate a new thread to handle each new client and then read the data at that thread. like:
TcpClient client = tcpListener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(new WaitHandle(HandleCleint), client);
private void HandleClient(object clientObject)
{
TcpClient client = (TcpClient)clientObject;
NetworkStream clientStream = client.GetStream();
//handle the data here
}
Edit: You stated at a comment:
I don't have an idea about how to change my program to send an entire queue to server side
Array or Queue itself is an object:
//at your client side:
bf.Serialize(clientStream, persons);//assume persons is Queue<Person>
//at your server side:
Queue<Person> persons = (Queue<Person>)bf.Deserialize(clientStream);
Ok. Finally I found the answer for my question doing some investigations/Testings. I ll post it here for someone else.. :)
In my client side first I have to send how much bytes im gonna send to server. and then send that data.. Like this..
Queue<Person> clientQueue; // This is the client side queue
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 15884);
var client = new TcpClient();
NetworkStream clientStream = client.GetStream()
while (disconnectClient)
{
if (clientQueue.Count > 0)
{
Person person = clientQueue.Dequeue();
using (MemoryStream memoryStrem = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(memoryStrem, person);
byte[] writeData = memoryStrem.ToArray();
byte[] writeDataLen = BitConverter.GetBytes((Int32)writeData.Length);
clientStream.Write(writeDataLen, 0, 4);
clientStream.Write(writeData, 0, writeData.Length);
}
}
}
clientStream.Dispose();
client.Dispose();
In Server Side :
Queue<Person> serverQueue; // This is the server side queue
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 15884);
TcpListener tcpListener = new TcpListener(ipEndPoint);
tcpListener.Start();
while(true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
NetworkStream clientStream = tcpClient.GetStream();
while (client.Connected)
{
if (client.Available >= 4)
{
try
{
byte[] readDataLen = new byte[4];
clientStream.Read(readDataLen, 0, 4);
Int32 dataLen = BitConverter.ToInt32(readDataLen, 0);
byte[] readData = new byte[dataLen];
clientStream.Read(readData, 0, dataLen);
using (var memoryStream = new MemoryStream())
{
memoryStream.Write(readData, 0, readData.Length);
memoryStream.Position = 0; /// This is very important. It took 4 hrs to identify an error because of this :)
BinaryFormatter bf = new BinaryFormatter();
Person person = (Person)bf.Deserialize(memoryStream);
serverQueue.Enqueue(person);
}
}
catch { }
}
}
tcpClient.Close();
}

Categories

Resources