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();
}
Related
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);
}
}
below is roughly how I normally do when trying to setup a connection on my server with my slient device:
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, nConst3rdPartyPort);
the3rdPartyListener = new Socket(localEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
the3rdPartyListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
the3rdPartyListener.Bind(localEP);
the3rdPartyListener.Listen(100);
the3rdPartyListener.BeginAccept(new AsyncCallback(AcceptConnectBack), the3rdPartyListener);
Any client device can connect to my server if they know the server ip and port number.
Now, I want to do filtering of client device. Only specific client device can connect to my server.
Is it that we can insert a unique ID to client so that the client with only that unique ID can connect to my server?
How do we ensure that the client is the specific client that we want?
This is for security reason to prevent unauthorized client from connecting to the server.
You can use IPEndPoint Address method to retrieve the remote IPAddress and make a whitelist to check who can connect your server.
string clientIP = ((IPEndPoint)(the3rdPartyListener.RemoteEndPoint)).Address.ToString();
------------------------------------------------------------------------------------------------------------------------------------
Updated:
I'm not sure Csharp Socket has verified device method or not. But I have a method on below.
Use NetworkStream to pass data from Client to Server that verified the client.
Server Side:
TcpClient client;
TcpListener server;
Thread thread;
Thread threadTwo;
byte[] datalength = new byte[4];
public Server()
{
InitializeComponent();
server = new TcpListener(IPAddress.Any, 2018);
server.Start();
thread = new Thread(() =>
{
client = server.AcceptTcpClient();
ServerReceive();
}
thread.Start();
}
void ServerReceive()
{
networkStream = client.GetStream();
threadTwo = new Thread(() =>
{
while ((i = networkStream.Read(datalength, 0, 4)) != 0)
{
byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
networkStream.Read(data, 0, data.Length);
this.Invoke((MethodInvoker)delegate
{
if(Encoding.Default.GetString(data) == "unique ID")
{
//Do your job
}
}
}
}
threadTwo.Start();
}
Client Side:
NetworkStream networkStream;
TcpClient client;
byte[] datalength = new byte[4];
public Client()
{
InitializeComponent();
try
{
client = new TcpClient("your server ip", 2018);
ClientSend("unique ID");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void ClientSend(string msg)
{
try
{
networkStream = client.GetStream();
byte[] data;
data = Encoding.Default.GetBytes(msg);
int length = data.Length;
byte[] datalength = new byte[4];
datalength = BitConverter.GetBytes(length);
networkStream.Write(datalength, 0, 4);
networkStream.Write(data, 0, data.Length);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I have this simple tcp server class
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
Console.WriteLine("Hello");
}
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));
Console.WriteLine("New connexion");
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
Console.WriteLine("Got Stream");
byte[] message = new byte[4096];
int bytesRead;
Console.WriteLine("Initializing..");
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
Console.WriteLine("Reading..");
bytesRead = clientStream.Read(message, 0, 4096);
Console.WriteLine("Received something");
}
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();
Console.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
}
I simply call it in the main function like this :
Server server = new Server();
And in a separate client program I have this class
class TheClient
{
public void ConnectV2()
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
for (int i = 0; i < 20; i++)
{
byte[] buffer = encoder.GetBytes("Hello Server! " + i.ToString() + " ");
Console.WriteLine("Processing..");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.WriteLine("Hello Server sent");
}
}
}
I call it in the main function like
TheClient tc = new TheClient();
tc.ConnectV2();
My problem is that the server program seems slower than the client, he don't react before the 13th, or more, message from the client :
[I can't post images because of reputation]
It reads the first dozen of messages in one go, and then reads the others one by one.
And if I make the server emit first, the client receive the message, but they both stop, like if both wait for the other to send something.
Can someone explain me this behavior ? How can I control and synchronize it ?
TCP is not message based. It provides a stream of bytes. It is your responsibility to separate messages. Also note, that you might receive only a part of a message in one Read call.
Here's a simple way to do that: Send the messages as individual lines. Possibly using StreamWriter. Receive the messages using StreamReader.ReadLine().
That way you can also use a more sane encoding such as Encoding.UTF8.
Besides that your code is actually fine and workable. It is extremely rare to see almost working TCP code on Stack Overflow. Most code is horribly broken. Congratulations.
It's because that your client AP is always sending data ,but your server AP cannot receive those data right away. So,those data stacked in buffer and then server AP receive all at once.
You can try:
Set fixed lengths when you send or receive data.
or
Receive and split data.
I have an application running at remote server which writes data (string) to its local port, I want to read this systems port by another C# application running at some other system, When i connect to this port of the remote machine I get an error that the target machine actively refused the connection.
Any suggestion will be appreciated.
I have tried this code:
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipaddress = IPAddress.Parse("192.168.1.12");
IPAddress add = new IPAddress(ipaddress.GetAddressBytes());
EndPoint ep = new IPEndPoint(add, 7862);
sock.Connect(ep);
if (sock.Connected)
{
byte[] bytes = new byte[256];
int i = sock.Receive(bytes);
Console.WriteLine(Encoding.UTF8.GetString(bytes));
}
Here 192.168.1.12 is the IP address of the remote system, where an application is writing string continuously to port 7862. I need to read the value from that port via a C# application
I had written a program like that while ago... i copy paste it as it is, dont forget to allow "port" to the firewall and NAT so that the packet actually gets through
class Transmitter
{
public Boolean Transmit(String ip ,String port, String data){
TcpClient client = new TcpClient();
int _port = 0;
int.TryParse(port, out _port);
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ip), _port);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(data);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
return true;
}
}
class Listener
{
private TcpListener tcpListener;
private Thread listenThread;
// Set the TcpListener on port 13000.
Int32 port = 8081;
IPAddress localAddr = IPAddress.Parse("192.168.1.3");
Byte[] bytes = new Byte[256];
MainWindow mainwind = null;
public void Server(MainWindow wind)
{
mainwind = wind;
this.tcpListener = new TcpListener(IPAddress.Any, port);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
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);
}
}
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
// System.Windows.MessageBox.Show("socket");
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
// System.Windows.MessageBox.Show("disc");
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
mainwind.setText(encoder.GetString(message, 0, bytesRead));
//System.Windows.MessageBox.Show(encoder.GetString(message, 0, bytesRead));
// System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
}
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();
}