How to make multiple clients with SimpleTcp? - c#

I have a connection with TCP / IP. I want a multiple connection. I'm using SimpleTcp. It is very simple and useful for single connection. Unfortunately, I don't know how to make multiple connections with SimpleTcp.
The code below is the one used for single connection.
public void EthernetConnect()
{
try
{
string IpAddress = Ip.Text;
int Port = Convert.ToInt32(PortName.Text);
SimpleTcpClient client = new SimpleTcpClient(IpAddress, Port, false, null, null);
if (!client.IsConnected)
{
client.Connect();
if (client != null)
{
if (client.IsConnected)
{
Console.WriteLine("Connected");
client.Events.DataReceived += EthernetDataReceived;
client.Events.Connected += EthernetConnected;
client.Events.Disconnected += EthernetDisconnected;
timer.Start();
}
else
{
Console.WriteLine("Not Connected");
}
}
}
else
{
client.Events.DataReceived -= EthernetDataReceived;
}
}
catch
{
}
}
EthernetDataReceived
private void EthernetDataReceived(object sender, DataReceivedFromServerEventArgs e)
{
try
{
var Data = e.Data;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
How can the EthernetDataReceived function in single connection be used in multiple connections? Creating a separate function for each link sounds ridiculous.
I can use different structures other than SimpleTcp. But I'm a beginner please help?

EthernetDataReceived is just an event handler that can be used to handle the DataReceived event from any SimpleTcpClient object. You can think of it as a method that may be called by any object from any thread.
Isn't there a problem if data comes from all of them at the same time?
Then the method will be called once per event that gets raised. This isn't an issue as long as you don't read or modify any shared data in the event handler. If you do this, you need to make the method thread-safe which is a topic of its own.
Also, how do I know which server data is coming from?
You should be able to cast the sender argument and check the properties of the SimpleTcpClient:
private void EthernetDataReceived(object sender, DataReceivedFromServerEventArgs e)
{
SimpleTcpClient client = (SimpleTcpClient)sender;
//...
}
Or check the DataReceivedFromServerEventArgs whatever that is.

Related

ConcurrentQueue.Count remains zero when socket receive adds data

I have some code that used to work for many years and even now in specific cases it works but in other cases I just cannot understand why it fails.
The following code is part of a Client class that uses a System.Net.Sockets.Socket for communication:
protected ConcurrentQueue<byte[]> ReadQueue { get; } = new ConcurrentQueue<byte[]>();
private void ReadTimer_Tick(object sender, EventArgs e) {
ReadTimer.Stop();
try
{
while (ReadQueue.Count > 0 && !IsDisposing)
{
try
{
if (this.ReadQueue.TryDequeue(out var data))
{
[...]
}
}
catch (Exception ex)
{
[...]
}
}
}
catch (Exception)
{
[...]
}
finally
{
if (IsConnected && !IsDisposing) ReadTimer.Start();
}
}
protected void EnqueueData(IEnumerable<byte> data)
{
ReadQueue.Enqueue(data.ToArray());
}
The ReadTimer ticks every millisecond if it is not stopped in order to process data from the ConcurrentQueue.
There are two uses of the code:
First case
I open a connection to a Socket port. After the connection is established I call the Socket.BeginReceive method of the Socket.
Second case
I listen to a Socket port and call the Socket.BeginAccept method. Within the ´callback´ method of BeginAccept I also call the BeginReceive method of the Socket.
In both cases the same method is called:
private void StartReceiving(SocketAnswerBuffer state)
{
try
{
Status = ClientStatus.Receiving;
_ = state.Socket.BeginReceive(
state.Buffer, 0,
state.Buffer.Length,
SocketFlags.None,
ReceiveCallback,
state
);
}
catch (Exception ex)
{
[...]
}
}
So in both cases the ReceiveCallback is used to handle incoming data:
private void OnReceive(IAsyncResult result)
{
if (result.AsyncState is SocketAnswerBuffer state)
{
try
{
var size = state.Socket.EndReceive(result);
if (size > 0)
{
var data = state.Buffer.Take(size).ToArray();
EnqueueData(data);
}
}
catch (Exception ex)
{
[...]
}
finally
{
Status = ClientStatus.Connected;
if (state != null && state.Socket.Connected)
StartReceiving(state);
}
}
}
In both cases the EnqueueData method is called.
In the first case everything works. When the ReadTimer ticks ReadQueue.Count is more than 0 and the loop handles all data collected so far and processes it.
In the second case EnqueueData is also called and enqueues data to the ReadQueue. But when the ReadTimer ticks ReadQueue.Count is 0 and nothing works.
What I really cannot understand is that debugging the code shows that ReadQueue.Count is larger than 0 on EnqueueData and the ReadQueue even grows but in ReadTimer_Tick the ReadQueue remains empty ... I neither clear nor redeclare ReadQueue and ReadTimer_Tick is the only method in code that tries to dequeue the data from ReadQueue.
Somehow creating a new class that includes the Timer, the ConcurrentQueue and the method that proceeds the data and using this class inside the class with the Socket forced the ConcurrentQueue to be in sync with the Timer and the method.

Class Inheriting from Mainwindow causes "the calling thread must be sta because many UI components require this"

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.

ircDotNet bot fails to get messages from IRC channel, long login/logout

I'm trying to write bot for irc channel, which will read messages from channel, recognize if they are commands to him and do some actions depends on command which was send.
I've choose ircDotNet because it was the only library that contains some examples how to use it, but they are actually very outdated, only half of them works. My lack of experience in C# and in programming at all don't allows me to understand stuff without good examples :(
So what my program does now:
logs in to server using password
joins channel
log-outs (very buggy)
I cant capture and send any messages from and to a channel and i cant log-out instantly.
Global classes that used for login and IrcClient class exemplar used everywhere in events
public IrcRegistrationInfo irc_iri
{
get
{
return new IrcUserRegistrationInfo()
{
NickName = "jsBot",
UserName = "jsBot",
RealName = "jsBot",
Password = "oauth:p4$$w0rdH3Re48324729214812489"
};
}
}
public IrcClient gIrcClient = new IrcClient();
Also all current events:
private void Form1_Load(object sender, EventArgs e)
{
try
{
gIrcClient.Connected += ircClient_Connected;
gIrcClient.Disconnected += gIrcClient_Disconnected;
gIrcClient.FloodPreventer = new IrcStandardFloodPreventer(1, 10000);
}
catch (Exception ex) { MessageBox.Show(ex.ToString());}
}
Login button code:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
if (!gIrcClient.IsConnected)
{
button1.Text = "Connecting...";
gIrcClient.Connect("irc.twitch.tv", 6667, false, irc_iri);
}
else
{
button1.Text = "Disconnecting...";
gIrcClient.Quit(5000, "bye");
}
}
Logic is: program checks if ircClient connected or not, and do some action. Then after that action appropriate event will raise, enable that button again. But that Quit function works very slow or don't works at all, bot will stay at channel until i don't close my program (maybe i need to dispose ircclient?)
Connect and disconnect events. In connect event, bot will join channel. Bot appears at channel after ~30 seconds after i press connect button, but connected event raised after 2-3 seconds. And same for disconnect - disconnect event raises quickly, but bot stays on channel for much longer time (about 120 seconds).
void ircClient_Connected(object sender, EventArgs e)
{
try
{
if (button1.InvokeRequired)
{
MethodInvoker del = delegate {
button1.Text = "Disconnect";
button1.Enabled = true; };
button1.Invoke(del);
}
else
{
button1.Text = "Disconnect";
button1.Enabled = true;
}
gIrcClient.Channels.Join("#my_channel");
gIrcClient.LocalUser.JoinedChannel += LocalUser_JoinedChannel;
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
void gIrcClient_Disconnected(object sender, EventArgs e)
{
if (!gIrcClient.IsConnected)
{
try
{
if (button1.InvokeRequired)
{
MethodInvoker del = delegate
{
button1.Text = "Connect";
button1.Enabled = true;
};
button1.Invoke(del);
}
else
{
button1.Text = "Connect";
button1.Enabled = true;
}
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
else gIrcClient.Disconnect();
}
Join channel and message received events. They are never raising, have no idea why.
void LocalUser_JoinedChannel(object sender, IrcChannelEventArgs e)
{
try
{
gIrcClient.Channels[0].MessageReceived += Form1_MessageReceived;
gIrcClient.LocalUser.SendMessage(e.Channel, "test");
MessageBox.Show(gIrcClient.Channels[0].Users[0].User.NickName);
MessageBox.Show("bot_join_channel_event_raised");
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
void Form1_MessageReceived(object sender, IrcMessageEventArgs e)
{
try
{
if (e.Text.Equals("asd"))
gIrcClient.LocalUser.SendMessage(e.Targets, "received");
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
So main question is: how do i catch messages from channel and how do i send message to channel? I would appreciate any examples. You can find all code in one piece here: http://pastebin.com/TBkfL3Vq
Thanks
You try to join channel before adding an event.
gIrcClient.Channels.Join("#my_channel");
gIrcClient.LocalUser.JoinedChannel += LocalUser_JoinedChannel;
My suggestion is try adding event first like this:
gIrcClient.LocalUser.JoinedChannel += LocalUser_JoinedChannel;
gIrcClient.Channels.Join("#my_channel");
There is a bug in the IRC.NET library and twitch.tv is using a non-standard message reply that is tripping up IRC.NET.
I have created a bug here describing it. But basically twitch sends "Welcome, GLHF!" as the RPL_WELCOME message. The IRC RFC describes the format of the message to be "Welcome to the Internet Relay Network !#".
IRC.NET parses GLHF out of the welcome message as your nick name, which is used for things like firing the JoinedChannel and MessageRecieved events.
My solution is to download the source code and to comment out where it sets the nick name when receiving the RPL_WELCOME message. It sets the Nickname correctly from the IrcRegistrationInfo passed into the IrcClient constructor and doesn't need to be parsed from the welcome message from twitch. Not sure if this is the case for other IRC servers.
The function is called ProcessMessageReplyWelcome in IrcClientMessageProcessing.cs:
/// <summary>
/// Process RPL_WELCOME responses from the server.
/// </summary>
/// <param name="message">The message received from the server.</param>
[MessageProcessor("001")]
protected void ProcessMessageReplyWelcome(IrcMessage message)
{
Debug.Assert(message.Parameters[0] != null);
Debug.Assert(message.Parameters[1] != null);
this.WelcomeMessage = message.Parameters[1];
// Extract nick name, user name, and host name from welcome message. Use fallback info if not present.
var nickNameIdMatch = Regex.Match(this.WelcomeMessage.Split(' ').Last(), regexNickNameId);
//this.localUser.NickName = nickNameIdMatch.Groups["nick"].GetValue() ?? this.localUser.NickName;
this.localUser.UserName = nickNameIdMatch.Groups["user"].GetValue() ?? this.localUser.UserName;
this.localUser.HostName = nickNameIdMatch.Groups["host"].GetValue() ?? this.localUser.HostName;
this.isRegistered = true;
OnRegistered(new EventArgs());
}
A more involved solution might be to refine the nick name Regex so it does not match on GLHF!, which I think is not a valid nickname.
IRC.NET uses case sensitive string comparisons for finding users by nickname. So the value you pass into the IrcRegistrationInfo for the nickname must match the casing that twitch uses in messages pertaining to you. Which is all lowercase.

Is it possible to refactor this EventWaitHandle to not use Thread.Sleep() to control the race condition?

I want to send a message from a server to all clients. There are 0-* clients. The server may or may not be running when a client is loaded. The functionality here works how I want it. I am trying to figure out if this can be done without Thread.Sleep()? Also note that the clients and the server are each in independant processes.
Server Portion
class NamedEventsServer
{
internal static void Main()
{
const string ewhName = "StickyNoteEwh";
EventWaitHandle ewh = null;
bool doesNotExist = false;
bool wasCreated;
// Attempt to open the named event.
try
{
ewh = EventWaitHandle.OpenExisting(ewhName);
}
catch (WaitHandleCannotBeOpenedException)
{
Console.WriteLine("Named event does not exist.");
doesNotExist = true;
}
if (doesNotExist)
{
// The event does not exist, so create it.
ewh = new EventWaitHandle(true,
EventResetMode.ManualReset,
ewhName,
out wasCreated);
if (wasCreated)
{
Console.WriteLine("Created the named event.");
}
else
{
Console.WriteLine("Unable to create the event.");
return;
}
}
ewh.Set();
Thread.Sleep(1000);//wait one second...giving threads enough time to all respond. Then stop triggering the event.
ewh.Reset();
//exit
}
}
Client Portion
class NamedEventsClient
{
internal static void Main()
{
const string ewhName = "StickyNoteEwh";
while (true)
{
EventWaitHandle ewh = null;
bool doesNotExist = false;
bool wasCreated;
// Attempt to open the named event.
try
{
ewh = EventWaitHandle.OpenExisting(ewhName);
}
catch (WaitHandleCannotBeOpenedException)
{
Console.WriteLine("Named event does not exist.");
doesNotExist = true;
}
if (doesNotExist)
{
// The event does not exist, so create it.
ewh = new EventWaitHandle(false,
EventResetMode.ManualReset,
ewhName,
out wasCreated);
if (wasCreated)
{
Console.WriteLine("Created the named event.");
}
else
{
Console.WriteLine("Unable to create the event.");
return;
}
}
Console.WriteLine("Wait on the event.");
ewh.WaitOne();
Console.WriteLine("Event was signaled.");
//Console.WriteLine("Press the Enter key exit.");
Thread.Sleep(1000);
//Console.ReadLine();
}
}
}
I guess it depends whether you're certain all clients are going to get their time-slice within on second. It sounds reasonable, but under extreme stress some clients might miss it. How crucial is that?
Anyway, I think this is exactly the kind of thing you should use ZeroMQ for. It's light-weight, and takes care of all the potential bugs for you.

How to use UdpClient.BeginReceive in a loop

I want to do this
for (int i = 0; i < 100; i++ )
{
Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
}
But instead of using UdpClient.Receive, I have to use UdpClient.BeginReceive. The problem is, how do I do that? There aren't a lot of samples using BeginReceive, and the MSDN example is not helping at all. Should I use BeginReceive, or just create it under a separate thread?
I consistently get ObjectDisposedException exception. I only get the first data sent. The next data will throw exception.
public class UdpReceiver
{
private UdpClient _client;
public System.Net.Sockets.UdpClient Client
{
get { return _client; }
set { _client = value; }
}
private IPEndPoint _endPoint;
public System.Net.IPEndPoint EndPoint
{
get { return _endPoint; }
set { _endPoint = value; }
}
private int _packetCount;
public int PacketCount
{
get { return _packetCount; }
set { _packetCount = value; }
}
private string _buffers;
public string Buffers
{
get { return _buffers; }
set { _buffers = value; }
}
private Int32 _counter;
public System.Int32 Counter
{
get { return _counter; }
set { _counter = value; }
}
private Int32 _maxTransmission;
public System.Int32 MaxTransmission
{
get { return _maxTransmission; }
set { _maxTransmission = value; }
}
public UdpReceiver(UdpClient udpClient, IPEndPoint ipEndPoint, string buffers, Int32 counter, Int32 maxTransmission)
{
_client = udpClient;
_endPoint = ipEndPoint;
_buffers = buffers;
_counter = counter;
_maxTransmission = maxTransmission;
}
public void StartReceive()
{
_packetCount = 0;
_client.BeginReceive(new AsyncCallback(Callback), null);
}
private void Callback(IAsyncResult result)
{
try
{
byte[] buffer = _client.EndReceive(result, ref _endPoint);
// Process buffer
MainWindow.Log(Encoding.ASCII.GetString(buffer));
_packetCount += 1;
if (_packetCount < _maxTransmission)
{
_client.BeginReceive(new AsyncCallback(Callback), null);
}
}
catch (ObjectDisposedException ex)
{
MainWindow.Log(ex.ToString());
}
catch (SocketException ex)
{
MainWindow.Log(ex.ToString());
}
catch (System.Exception ex)
{
MainWindow.Log(ex.ToString());
}
}
}
What gives?
By the way, the general idea is:
Create tcpclient manager.
Start sending/receiving data using udpclient.
When all data has been sent, tcpclient manager will signal receiver that all data has been sent, and udpclient connection should be closed.
It would seem that UdpClient.BeginReceive() and UdpClient.EndReceive() are not well implemented/understood. And certainly compared to how the TcpListener is implemented, are a lot harder to use.
There are several things that you can do to make using the UdpClient.Receive() work better for you. Firstly, setting timeouts on the underlying socket Client will enable control to fall through (to an exception), allowing the flow of control to continue or be looped as you like. Secondly, by creating the UDP listener on a new thread (the creation of which I haven't shown), you can avoid the semi-blocking effect of the UdpClient.Receive() function and you can effectively abort that thread later if you do it correctly.
The code below is in three parts. The first and last parts should be in your main loop at the entry and exit points respectively. The second part should be in the new thread that you created.
A simple example:
// Define this globally, on your main thread
UdpClient listener = null;
// ...
// ...
// Create a new thread and run this code:
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 9999);
byte[] data = new byte[0];
string message = "";
listener.Client.SendTimeout = 5000;
listener.Client.ReceiveTimeout = 5000;
listener = new UdpClient(endPoint);
while(true)
{
try
{
data = listener.Receive(ref endPoint);
message = Encoding.ASCII.GetString(data);
}
catch(System.Net.Socket.SocketException ex)
{
if (ex.ErrorCode != 10060)
{
// Handle the error. 10060 is a timeout error, which is expected.
}
}
// Do something else here.
// ...
//
// If your process is eating CPU, you may want to sleep briefly
// System.Threading.Thread.Sleep(10);
}
// ...
// ...
// Back on your main thread, when it's exiting, run this code
// in order to completely kill off the UDP thread you created above:
listener.Close();
thread.Close();
thread.Abort();
thread.Join(5000);
thread = null;
In addition to all this, you can also check UdpClient.Available > 0 in order to determine if any UDP requests are queued prior to executing UdpClient.Receive() - this completely removes the blocking aspect. I do suggest that you try this with caution as this behaviour does not appear in the Microsoft documentation, but does seem to work.
Note:
The MSDN exmaple code you may have found while researching this problem requires an additional user defined class - UdpState. This is not a .NET library class. This seems to confuse a lot of people when they are researching this problem.
The timeouts do not strictly have to be set to enable your app to exit completely, but they will allow you to do other things in that loop instead of blocking forever.
The listener.Close() command is important because it forces the UdpClient to throw an exception and exit the loop, allowing Thread.Abort() to get handled. Without this you may not be able to kill off the listener thread properly until it times out or a UDP packet is received causing the code to continue past the UdpClient.Receive() block.
Just to add to this priceless answer, here's a working and tested code fragment. (Here in a Unity3D context but of course for any c#.)
// minmal flawless UDP listener per PretorianNZ
using System.Collections;
using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;
void Start()
{
listenThread = new Thread (new ThreadStart (SimplestReceiver));
listenThread.Start();
}
private Thread listenThread;
private UdpClient listenClient;
private void SimplestReceiver()
{
Debug.Log(",,,,,,,,,,,, Overall listener thread started.");
IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Any, 1260);
listenClient = new UdpClient(listenEndPoint);
Debug.Log(",,,,,,,,,,,, listen client started.");
while(true)
{
Debug.Log(",,,,, listen client listening");
try
{
Byte[] data = listenClient.Receive(ref listenEndPoint);
string message = Encoding.ASCII.GetString(data);
Debug.Log("Listener heard: " +message);
}
catch( SocketException ex)
{
if (ex.ErrorCode != 10060)
Debug.Log("a more serious error " +ex.ErrorCode);
else
Debug.Log("expected timeout error");
}
Thread.Sleep(10); // tune for your situation, can usually be omitted
}
}
void OnDestroy() { CleanUp(); }
void OnDisable() { CleanUp(); }
// be certain to catch ALL possibilities of exit in your environment,
// or else the thread will typically live on beyond the app quitting.
void CleanUp()
{
Debug.Log ("Cleanup for listener...");
// note, consider carefully that it may not be running
listenClient.Close();
Debug.Log(",,,,, listen client correctly stopped");
listenThread.Abort();
listenThread.Join(5000);
listenThread = null;
Debug.Log(",,,,, listener thread correctly stopped");
}
I think you should not use it in a loop but instead whenever the BeginReceive callback is called you call BeginReceive once more and you keep a public variable for count if you want to limit the number to 100.
have look at MSDN first. They provide good example.
http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.beginreceive.aspx
I would do network communication on a background thread, so that it doesn't block anything else in your application.
The issue with BeginReceive is that you must call EndReceive at some point (otherwise you have wait handles just sitting around) - and calling EndReceive will block until the receive is finished. This is why it is easier to just put the communication on another thread.
You have to do network operations, file manipulations and such things that are dependent to other things rather than your own program on another thread (or task) because they may freeze your program. The reason for that is that your code executes sequentially.
You have used it in a loop which is not fine. Whenever BeginRecieve callback is invoked you should call it again. Take a look at the following code:
public static bool messageReceived = false;
public static void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;
Byte[] receiveBytes = u.EndReceive(ar, ref e);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("Received: {0}", receiveString);
messageReceived = true;
}
public static void ReceiveMessages()
{
// Receive a message and write it to the console.
IPEndPoint e = new IPEndPoint(IPAddress.Any, listenPort);
UdpClient u = new UdpClient(e);
UdpState s = new UdpState();
s.e = e;
s.u = u;
Console.WriteLine("listening for messages");
u.BeginReceive(new AsyncCallback(ReceiveCallback), s);
// Do some work while we wait for a message. For this example,
// we'll just sleep
while (!messageReceived)
{
Thread.Sleep(100);
}
}

Categories