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.
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 trying to develop a software (in C#) that collect some data on a list (List<string> socketList). The value of this list must be sent to a processing software.
In this program, the server (the C# software) waits for a message from a client (the Processing software) and send an element of the list. This list is continuously filled by a method in another thread (I verify, the list is everytime full). I used this method because I need that each value has to arrive at a client, no matter the speed.
Here there is the method in C# (it is launched as a thread):
public static void InizializeSocket()
{
//setting the comunication port
int port = 5000;
//infinite loop in order to accept sequential clients
while (true)
{
//I open the listener for any IP
TcpListener listener = new TcpListener(IPAddress.Any, port);
Console.WriteLine("Listening...");
//Waiting for a client
listener.Start();
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("CONNECTED");
//this string will contain the client message
String dataReceived = "";
//loop until "q". If the client send a message with a q, the server disconnect the client
while (dataReceived != "q")
{
//Read the client message
NetworkStream nwStream = client.GetStream();
try
{
//Define the client message buffer dimension and read the message
byte[] buffer = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//Encoding the byte in a string
dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
//check if the List<string> socketList is not empty. If it has any elements, I send the first one and after that I remove the element from the list
if (socketList.Count > 0)
{
//Encoding the string in a byte
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(socketList[0]);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
socketList.RemoveAt(0);
}
nwStream.Flush();
}
catch (Exception e) { dataReceived = "q"; }
}
//Exit from the client loop
Console.WriteLine("DISCONNECTED");
client.Close();
listener.Stop();
}
}
And here the simple Processing software
import processing.net.*;
Client myClient;
String dataIn;
int port = 5000;
String ip = "127.0.0.1";
void setup () {
size(1100, 1025);
//Initialize the client
myClient = new Client(this, "127.0.0.1", 5000);
}
void draw () {
//If the client is available it send a generic message to the server and try to receive a response
if (myClient.available() > 0) {
myClient.write("c");
dataIn = myClient.readString();
}
//print the output in debug
println(dataIn);
}
Here the Processing software is able to connect, anyway, I received every time null.
In addition, if I try to write (in the try on the C# software) only:
if (socketList.Count > 0)
{
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(socketList[0]);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
socketList.RemoveAt(0);
}
I receive strange values that are not the same values in the list stored in C# software.
So, why in the first case processing read only null value? And why in the second case it read "random" value?
EDIT:
Analyze better the programs flow, I verify where is the problem. I rewrite the processing socket as a java socket. It is launched in another thread and fills an ArrayList.
Considering a simplification of the code (in order to understand better), if I write:
Socket s = new Socket("localhost", 5000);
BufferedReader input =new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out= new PrintWriter(s.getOutputStream(), true);
out.println("hello");
String temp = input.readLine();
the software blocks on String temp = input.readLine();. Anyway, the communication is established and I am sure that C# send the string.
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.
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();
}
I am working on a c# and php project where the PHP script opens a socket to a c# program and the c# program will read the data and then send a response back.
In the PHP script I have the following:
echo "Opening Client";
$fp = fsockopen("127.0.0.1", 12345, $errno, $errstr, 30);
if (!$fp)
{
echo "Error: $errstr ($errno)<br />";
}
else
{
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: 127.0.0.1\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp))
{
echo fgets($fp, 128);
}
fclose($fp);
}
In the C# project I have the following:
public void startListen()
{
int port = 12345;
IPAddress serverAddress = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(serverAddress, 12345);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
byte[] data = new byte[client.ReceiveBufferSize];
int bytesRead = stream.Read(data, 0, Convert.ToInt32(client.ReceiveBufferSize));
string request = Encoding.ASCII.GetString(data, 0, bytesRead);
Console.WriteLine(request);
Console.ReadLine();
The PHP script seems to stay waiting and doesn't finish, I'm guessing its being its because the socket on the c# app to send a response back but I have no idea how to do this. Another problem, in the C# I need to have Console.ReadLine() otherwise the c# program will exit but the PHP Script does then finish as expected.
Basically, what I want to know is this the best way to read the data that is sent on the socket, what is the best way to keep the program running so it keep on listening on the socket and how I send back a reply so that the php script can finish.
Thanks for any help you can provide.
I managed to figure this out, after processing the data I need to then send a stream.write which is what sends the reply back.
Below is the code
int port = 12345;
IPAddress serverAddress = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(serverAddress, port);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
byte[] data = new byte[client.ReceiveBufferSize];
int bytesRead = stream.Read(data, 0, Convert.ToInt32(client.ReceiveBufferSize));
string request = Encoding.ASCII.GetString(data, 0, bytesRead);
Console.WriteLine(request);
byte[] msg = System.Text.Encoding.ASCII.GetBytes("200 OK");
// Send back a response.
stream.Write(msg, 0, msg.Length);
client.Close();
}
Thanks for your help
Mr. Boardy's solution is correct but I think doing this by socket is better.
So the socket solution is:
private void Form3_Load(object sender, EventArgs e)
{
sc_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ip_local = new IPEndPoint(IPAddress.Loopback, 1225);
sc_listener.Bind(ip_local);
sc_listener.Listen(10);
AsyncCallback callback = new AsyncCallback(procces_incoming_socket);
sc_listener.BeginAccept(callback, sc_listener);
}
void procces_incoming_socket(IAsyncResult socket_object)
{
Socket sc_listener = ((Socket)socket_object.AsyncState).EndAccept(socket_object);
AsyncCallback receive = new AsyncCallback(receive_data);
buffer = new byte[100];
sc_listener.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receive, sc_listener);
}
void receive_data(IAsyncResult socket)
{
// the system need to wait so i make a loop when it gets data
//i end the loop by flag=false
bool flag = true;
Socket re_socket = ((Socket)socket.AsyncState);
while(flag)
{
int bytes_recieved = re_socket.EndReceive(socket);
string data = UTF8Encoding.UTF8.GetString(buffer);
if (textBox1.InvokeRequired)
{
// for cross thread problem
textBox1.Invoke(new MethodInvoker(delegate { textBox1.Text = data; }));
}
else
{
textBox1.Text = data;
}
flag = false;
}
string back_data = "my pm socket back";
byte[] buffers = new byte[50];
buffers = UTF8Encoding.UTF8.GetBytes(back_data);
re_socket.Send(buffers);
// if the socket is not closed php will load for maximum required time and then error
re_socket.Close();
//start for next listening (O-0)
AsyncCallback callback = new AsyncCallback(procces_incoming_socket);
sc_listener.BeginAccept(callback, sc_listener);
}
I am not a php guy by any stretch of the imagination so my answer is contingent upon php being able to respond correctly. On the C# side, create a while/do-while loop that continues to run to accept the next incoming request. Here's a simple example:
http://www.csharp-examples.net/socket-send-receive/
Make sure to set the NoDelay option so that the information is flushed.