I am working on a windows service that should collect all incoming TCP/IP streams with this class. It gets started from the services OnStart() void.
However I have encountered that when messages come in from a second sender, the whole communication stops working. The service then does not react to a single connection until you restart it.
public class TCPIP
{
public static Receiver rc = new Receiver();
public class Receiver
{
public delegate void ReceivedEventHandler(string ReceivedText, string Sender);
public event ReceivedEventHandler Received;
public void Start()
{
System.Threading.Thread th = new System.Threading.Thread(internals);
th.Start();
}
private void internals()
{
TcpListener _listener = new TcpListener(1994);
_listener.Start();
while (true)
{
TcpClient rcclient = _listener.AcceptTcpClient();
StreamReader reader = new StreamReader(rcclient.GetStream());
string msg = "";
while (reader.Peek() > -1)
{
msg += Convert.ToChar(reader.Read()).ToString();
}
Received(msg, rcclient.Client.RemoteEndPoint.ToString().Split(Convert.ToChar(":"))[0]);
// Cleanup
rcclient.Close();
reader.Close();
}
}
Could anybody help me out improving this class to answer connections from multiple endpoints, and to not be occupied after one?
Thank you very much in advance.
Just create a thread when you accept some connection, so if it's blocked will not afect the main program.
Btw you can try AcceptTcpClientAsync to prevent blocking calls.
Related
I'm trying to create my own chat app as a school project.
I have almost everything ready, connected with DB, backend. The only thing that is weighing me down right now is adding a TCP Server to the project for communication between Clients.
It's not supposed to be anything big, so just short code, plus I don't have that much experience with TCP in C#.
The code works, but the problem is that the Application/Window doesn't appear.
I suspected that the problem might be in the MainWindow() constructor due to the infinite loop (this was also confirmed here on SO). Unfortunately I don't know how to fix it anymore. I first had the server as a separate class, but I ran into this problem. So I tried implementing it directly in the class, or breaking the connection after shutting down the application.
public partial class MainWindow: Window {
private TcpListener myServer;
private bool isRunning;
public MainWindow() {
InitializeComponent();
myServer = new TcpListener(IPAddress.Any, 65525);
myServer.Start();
isRunning = true;
LoopServer();
}
private void LoopServer() {
while (isRunning) {
TcpClient client = myServer.AcceptTcpClient();
Thread thread = new Thread(new ParameterizedThreadStart(LoopClient));
thread.Start(client);
}
}
private void LoopClient(object obj) {
TcpClient client = (TcpClient) obj;
StreamReader reader = new StreamReader(client.GetStream(), Encoding.UTF8);
StreamWriter writer = new StreamWriter(client.GetStream(), Encoding.UTF8);
MessageBox.Show("Connected bro!");
writer.Flush();
bool clientRunning = true;
while (clientRunning) {
string data = reader.ReadLine();
MessageBox.Show(data);
writer.Flush();
}
}
}
An infinite loop is okay for a server to be running in. Generally, you can start up the server (1st application). The clients (different application) can connect to it and then process messages and broadcast them to all the clients appropriately.
Super simple example: Build Chat in C#
Alternatively you can try an event based approach to the TCP listener.
I'm trying my hands on NetMQ (3.3.3.4) and creating a pub-sub pattern.
I want a host/server to listen to all incoming data on one port (9000) and forward the data to all clients/subscribers on another port (9001).
The clients will then send data on 9000 and receive all messages sent (by whomever) on 9001.
Following the documentation I created something like the code below, but I can't get it to work. Mainly, I believe, because ReceiveReady is never called!
How I believe it should work:
client.Publish should cause the first line in host.SubscriberSocket_ReceiveReady to unblock and pass the data along to the other socket
When data has been passed along it should appear in the infinite running Task in the client
Results:
Breakpoints on // This line is never reached are never reached
There are no exceptions anywhere.
Switching the ports on the host so that publish = 9000 and subscribe = 9001 has no effect
Windows Firewall is turned off, so there should not be any blocking
It makes no difference if I'm putting the address into PublisherSocket constructor, or if I'm using _publisherSocket.Bind(address) in Host or _publisherSocket.Connect(address) in Client
What am I doing wrong?
Host
public class MyNetMQHost {
private NetMQSocket _publishSocket;
private NetMQSocket _subscribeSocket;
private NetMQPoller _poller;
public MyNetMQHost(string publishAddress = "#tcp://localhost:9001", string subscribeAddress = "#tcp://localhost:9000") {
Task.Factory.StartNew(() => {
using (_publishSocket = new PublisherSocket(publishAddress))
using (_subscribeSocket = new SubscriberSocket(subscribeAddress))
using (_poller = new NetMQPoller { _publishSocket, _subscribeSocket }) {
_subscriberSocket.ReceiveReady += SubscriberSocket_ReceiveReady;
_poller.Run();
}
});
}
private void SubscriberSocket_ReceiveReady(object sender, NetMQSocketEventArgs e) {
var data = e.Socket.ReceiveMultipartBytes(); // This line is never reached
_publishSocket.SendMultipartBytes(data);
}
}
Client
public class MyNetMQClient {
private readonly NetMQSocket _publishSocket;
private readonly NetMQSocket _subscribeSocket;
public MyNetMQClient(string publishAddress = ">tcp://localhost:9000", string subscribeAddress = ">tcp://localhost:9001") {
_publishSocket = new PublisherSocket(publishAddress);
_subscribeSocket = new SubscriberSocket(subscribeAddress);
Task.Factory.StartNew(() => {
while (true) {
byte[] frameBytes = _subscribeSocket.ReceiveFrameBytes();
int one = 1; // This line is never reached
}
});
}
public void Publish(byte[] data) {
_publishSocket.SendFrame(data);
}
}
Tester
public class Tester {
public void MyTester() {
MyNetMQHost host = new MyNetMQHost();
MyNetMQClient client = new MyNetMQClient();
client.Publish(Encoding.Unicode.GetBytes("Hello world!");
}
}
Both your broker and client never call suscribe.
On the broker call suscriber.Subscribe("") to subscribe for all. On your client subscribe to what ever you want.
In your broker you should actually use XSubscriber and XPublisher to move susvriptions around. That way you dont need the subscribe all. You can use Proxy class for that.
I'm working on a Chat server which receives connections from multiple clients and sends/receives messages.
This is how it gets connections from the clients:
public void StartServer()
{
tcpListener = new TcpListener(IPAddress.Any, 60000);
tcpListener.Start();
listenTask = Task.Factory.StartNew(() => ListenLoop());
}
private async void ListenLoop()
{
int i = 0;
for (; ; )
{
var socket = await _tcpListener.AcceptSocketAsync();
if (socket == null)
break;
var c = new Client(socket, i);
i++;
}
}////Got this code from somewhere here, not really what I want to use (discussed down)
This is the Client class:
public class Client
{
//irrelevant stuff here//
public Client(Socket socket, int number)
{
//irrelevant stuff here//
Thread ct = new Thread(this.run);
ct.Start();
}
public void run()
{
writer.Write("connected"); //Testing connection
while (true)
{
try
{
string read = reader.ReadString();
// Dispatcher.Invoke(new DisplayDelegate(DisplayMessage), new object[] { "[Client] : " + read });
}////////Not working, because Client needs to inherit from MainWindow.
catch (Exception z)
{
MessageBox.Show(z.Message);
}
}
}
}
Ok so problem is, to update the UI Client class must inherit from MainWindow, but when it does, I get "the calling thread must be sta because many UI components require this" error. When it doesn't inherit it works just fine.
Another problem is, I want to use a Client[] clients array and then when a user connects, it adds him to the array so that i can individually write/read to/from specific clients.
while (true)
{
try
{
clients[counter] = new Client(listener.AcceptSocket(), counter);
counter ++;
MessageBox.Show("client " + counter.ToString());
}
catch (Exception e) { MessageBox.Show(e.Message); }
}
Problem here is, i get "Object refrence not set to an instance of an object" when a client connects.
Any ideas how to fix both/any of these problems?
Sorry code might be a bit messed up but I tried lots of stuff to get it working so I ended up with lots of junk in the code.
Thanks in advance.
I have a simple TCP server based on the TcpListener. Since I want to use it in a Windows Form application I made it run in a separate thread as follows:
public void Start() {
this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
this.serverThread.Name = "Tcp-Server";
this.serverThread.Start();
}
protected void ThreadProcess() {
try
{
IPAddress ipAd = IPAddress.Parse("169.254.42.86");
this.listener = new TcpListener(ipAd, this.port);
this.listener.Start();
Socket mySocket = this.listener.AcceptSocket();
while (true)
{
if (mySocket.Connected)
{
byte[] RecvBytes = new byte[8192];
int byteNo = mySocket.Receive(RecvBytes, RecvBytes.Length, 0);
ASCIIEncoding asen = new ASCIIEncoding();
mySocket.Send(asen.GetBytes("srv reply msg"));
}
else
{
WriteLine("socket not connected.");
}
}
}
finally {
StopListener();
}
}
If I use this server in a console application as:
static void Main(string[] args)
{
try
{
int port = 8001;
Server server = new Server(port);
server.Start();
while (true) {
//server is running in separate thread
}
...
everything works as expected. However, when I try to include it in a Windows-Form Application that starts the server when a button is clicked, the code doesn't work any more. The server thread is being launched, but it doesn't accept any sockets.
Is there something that I am missing? I have been searching high and low on google without result...
Thanks for any help!
Not really an answer but too much to type in the comments:
The easiest way to debug this issue is to simply call the ThreadProcess() method in the same thread:
public void Start() {
ThreadProcess();
//this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
//this.serverThread.Name = "Tcp-Server";
//this.serverThread.Start();
}
You can then step through your code to see what happens. As soon as you hit the this.listener.AcceptSocket(); line your application will block, but you should be able to connect to it.
Usually the problem is something silly everyone overlooks like the Start() method not being called.
I am creating my first app its a little server. I just wanted to know whats the best way to accept multiple connections but not be flooded, say 10 connections in 10 secounds then if flooded close the listener. Would threads or thread pool help me do this.
I added the Threadpool but not sure on how i should be using it for my application.
Please take a look at my code below and see what I need to do to make it secure and not get flooded.
Thanks
class Listener
{
public static TcpListener _listener;
private static TcpClient _client;
private static NetworkStream _clientStream;
public Listener(string ip, Int32 port)
{
ThreadPool.SetMaxThreads(50, 100);
ThreadPool.SetMinThreads(50, 50);
// Set the TcpListener IP & Port.
IPAddress localAddr = IPAddress.Parse(ip);
_listener = new TcpListener(localAddr, port);
}
public void Start() // Run this on a separate thread, as
{ // we did before.
_listener.Start();
Console.WriteLine("Starting server...\n");
Console.WriteLine("Listening on {0}:{1}...", Globals._localIP, Globals._port);
while (Globals._Listen)
{
try
{
if (!_listener.Pending())
{
Thread.Sleep(500); // choose a number (in milliseconds) that makes sense
continue; // skip to next iteration of loop
}
Globals._requestCounter += +1;
// Get client's request and process it for web request.
ProcessRequest();
}
catch (SocketException e)
{
// Listener Error.
}
catch (InvalidOperationException er)
{
}
}
_listener.Stop();
}
public static void Stop()
{
Globals._Listen = false;
}
}
static void Main(string[] args)
{
// Set listener settings.
var server = new Listener(Globals._localIP, Globals._port);
// Start the listener on a parallel thread:
Thread listenerThread = new Thread(server.Start);
listenerThread.Start();
Thread.Sleep(500);
}
For TCP in .NET I highly recommend using WCF rather than trying to roll your own. For your needs there is a "TCP port sharing service", you just need to enable it. Also things like throttling, message size limts are all already taken care of you just need to configure it. There are also a variety of ways of using WCF net.tcp, it can do streaming, peer to peer, full duplex etc, so there are very few scenarios where you have to roll your own.