I have an application that runs and continuously in the system tray icon. It makes sure it is the only running instance of my application by running some code that uses a #Global mutex.
Due to 3rd party vendor limitations the only (sane) way I can integrate with one part of a vendor app is by specifying in a config file that an arbitrary command line executable is called. The parameters I care about are automatically added to the executable I specify.
So I think most people who integrated with this run a seperate program which connects to a server socket on the main program and sends a packet letting the main program know the command line has been triggered.
I'm wondering if there is a way I could do this pseudo-code..
static void Main(string[] args)
{
if (isrunningcommandLine)
{
ConnectToAlreadyRunningProcessAndPassInfo(args); // find already running process by its process name and somehow pass the command line params
KillProgram();
}
else
{
CheckGlobalMutexAndStart();
}
}
Essentially if I am running via command line connect to the already running global process and pass it some data.
I control the code that will be the client as well as the server, they are in fact the same project.
You can use a global named mutex to detect if your app is already running.
If no run a server that will receive and manage the commands.
If yes run a client and just send the commands to the server.
Then use a TCP connection on localhost to exchange messages.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Test42
{
internal static class Program
{
private static int PORT = 1337;
private static void Main()
{
bool ok;
// Try to build a mutex.
var mutex = new Mutex(true, #"Test42", out ok);
// If build is ok, we run as a server.
// Otherwise, the server is already running, so we run as a client.
if (ok)
{
var server = new MyServer(PORT);
server.Start();
}
else
{
var r = new Random();
var message = "Ho Hey : " + r.Next(50);
var client = new MyClient();
client.Send(PORT, message);
}
}
}
internal class MyClient
{
/// <summary>
/// Send a message to localhost.
/// </summary>
/// <param name="port">The port to connect.</param>
/// <param name="message">The message to send.</param>
public void Send(int port, string message)
{
var client = new TcpClient();
var serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
client.Connect(serverEndPoint);
using (var stream = client.GetStream())
{
var messageBuffer = Encoding.Unicode.GetBytes(message);
var lengthBuffer = BitConverter.GetBytes(messageBuffer.Length);
// Send message length.
stream.Write(lengthBuffer, 0, lengthBuffer.Length);
// Send message.
stream.Write(messageBuffer, 0, messageBuffer.Length);
stream.Flush();
}
client.Close();
}
}
internal class MyServer
{
private readonly int _port;
public MyServer(int port)
{
_port = port;
}
public void Start()
{
Console.WriteLine("wait for messages");
var thread = new Thread(ThreadStart);
thread.Start();
}
private void ThreadStart()
{
var listener = new TcpListener(IPAddress.Any, _port);
listener.Start();
while (true)
{
var client = listener.AcceptTcpClient();
var clientThread = new Thread(ClientThreadStart);
clientThread.Start(client);
}
}
private void ClientThreadStart(object obj)
{
var client = obj as TcpClient;
if (client == null) return;
using (var stream = client.GetStream())
{
const int lengthLength = sizeof(int) / sizeof(byte);
// Read the message length.
var lengthBuffer = new byte[lengthLength];
stream.ReadAsync(lengthBuffer, 0, lengthLength).Wait();
var messageLength = BitConverter.ToInt32(lengthBuffer, 0);
// Read the message.
var messageBuffer = new byte[messageLength];
stream.ReadAsync(messageBuffer, 0, messageLength).Wait();
var message = Encoding.Unicode.GetString(messageBuffer);
Console.WriteLine("Client says: " + message);
}
client.Close();
}
}
}
Related
I tried to send form a single UdpClient to several different open UDP sockets from localhost to localhost. However in the first version only the first message of the loop was sent, the rest did not even make it out.
When trying to isolate the error the second call to udpClient.Connect() raises a SocketException pointing to the Error WSAEISCONN 10056
The official documentation of UdpClient.Connect() here states in the remark section if you want to send to different endpoints, call Connect again. However this is the opposite of what the error tells me.
So is this just an error in the docs of the Connect methode, or do I miss something here?
Too fast requests should not be an issue with only 3 requests every 3 Seconds and as I use the normal Send(buffer) call, there should be no packets waiting to be sent to the previous endpoint.
Simple example to reproduce (I used .net 6, Win10):
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace UdpClientIssue;
internal class Program
{
static void Main(string[] args)
{
var sender = CreateSender(3_000, 40001, 40002, 40003);
var reciverA = CreateReciver("ReciverA", 40001);
var reciverB = CreateReciver("ReciverB", 40002);
var reciverC = CreateReciver("ReciverC", 40003);
reciverA.Start();
reciverB.Start();
reciverC.Start();
sender.Start();
sender.Join();
}
static void Reciver(int port)
{
var localEP = new IPEndPoint(IPAddress.Loopback, port);
using var listener = new UdpClient(localEP);
var buff = new byte[1024];
while (true)
{
var senderEP = new IPEndPoint(IPAddress.None, 0);
var data = listener.Receive(ref senderEP);
var message = Encoding.UTF8.GetString(data);
Console.WriteLine($"Recived at {port}: {message}");
}
}
static void Sender(int interval_ms, params int[] ports)
{
int messageNumber = 0;
while (true)
{
Thread.Sleep(interval_ms);
using (var udpClient = new UdpClient())
{
foreach (var remotePort in ports)
{
var message = $"Message {++messageNumber} to {remotePort}";
var sendBuffer = Encoding.UTF8.GetBytes(message);
Console.WriteLine($"Sending to {remotePort}: {message}");
var remoteEP = new IPEndPoint(IPAddress.Loopback, remotePort);
//This errors on second iteration
//udpClient.Connect(remoteEP);
//udpClient.Send(sendBuffer);
//This works
udpClient.Send(sendBuffer, remoteEP);
}
}
messageNumber += 100 - ports.Length;
}
}
static Thread CreateReciver(string name, int port)
{
var ts = new ThreadStart(() => Reciver(port));
var t = new Thread(ts)
{
Name = name
};
return t;
}
static Thread CreateSender(int interval_ms, params int[] ports)
{
var ts = new ThreadStart(() => Sender(interval_ms, ports));
var t = new Thread(ts)
{
Name = "Sender"
};
return t;
}
}
I believe it's error in the docs. Description of this error message says:
Socket is already connected.
A connect request was made on an already-connected socket
And source code explicitly throws this exception with this error code if socket was already connected.
Here you see it just forwards connect to Socket:
public void Connect(IPEndPoint endPoint)
{
ThrowIfDisposed();
ArgumentNullException.ThrowIfNull(endPoint);
CheckForBroadcast(endPoint.Address);
Client.Connect(endPoint);
_active = true;
}
And in Socket.Connect you see it throws this errors if socket is already connected:
if (_isConnected)
{
throw new SocketException((int)SocketError.IsConnected);
}
Fortunately you already know the better way of doing this - just pass remote endpoint to Send call. UDP is connectionless protocol anyway so calling Connect only sets default remote endpoint and doesn't perform actual connection.
I've created an universal app that connects to a WCF webservice at intranet, an it's working just fine, since the address of the service's host is known.
The system's architecture allows to be more than one webservice running, in different hosts, for performance and security (redundancy) reasons. So I'm trying to make my app discover every service, with the given contract, that is been running on the same LAN, but I can't manage to do that.
I'm trying the same approach used at a very similar win32 app:
var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var findCriteria = new FindCriteria(typeof(INewProdColetorWCFService));
findCriteria.Duration = TimeSpan.FromSeconds(5);
var findResponse = await discoveryClient.FindTaskAsync(findCriteria);
Visual Studio "automatically" adds the needed reference (System.ServiceModel.Discovery) for me as seen here
At design time it seems to be ok, but when i try to compile, that error appear:
Cannot find type System.ServiceModel.Configuration.ServiceModelConfigurationElementCollection`1 in module System.ServiceModel.dll.
Have any of you did that in UWP? Can you help me?
Thanks in advance, iuri.
ps: I've posted this question in MSDN too
I came across this thread whilst doing some research myself. After reading up on https://en.wikipedia.org/wiki/WS-Discovery and using Wireshark to decipher some of the specifics, I've got a basic proof of concept that supports Microsoft's WS-Discovery specification, meaning no changes are necessary on the server end.
I've jumped off the project for now, but hopefully someone might get some use from it:
public class WSDiscoveryResponse
{
private readonly string
_content,
_remotePort;
private readonly HostName
_remoteAddress;
public WSDiscoveryResponse(string content, HostName remoteAddress, string remotePort)
{
this._content = content;
this._remoteAddress = remoteAddress;
this._remotePort = remotePort;
}
}
public class WSDiscoveryClient
{
private const string
SRC_PORT = "0",//represents 'use any port available'
DEST_IP_WSDISCOVERY = "239.255.255.250", //broadcast (ish)
DEST_PORT_WSDISCOVERY = "3702";
private TimeSpan _timeout = TimeSpan.FromSeconds(5);
private List<WSDiscoveryResponse> _wsresponses = null;
/// <summary>
/// Get available Webservices
/// </summary>
public async Task<List<WSDiscoveryResponse>> GetAvailableWSEndpoints()
{
_wsresponses = new List<WSDiscoveryResponse>();
using (var socket = new DatagramSocket())
{
try
{
socket.MessageReceived += SocketOnMessageReceived;
//listen for responses to future message
await socket.BindServiceNameAsync(SRC_PORT);
//broadcast interrogation
await SendDiscoveryMessage(socket);
//wait for broadcast responses
await Task.Delay(_timeout).ConfigureAwait(false);
}
catch (Exception ex)
{
SocketErrorStatus webErrorStatus = SocketError.GetStatus(ex.GetBaseException().HResult);
}
}
return _wsresponses;
}
private string BuildDiscoveryMessage()
{
const string outgoingMessageFormat = #"<s:Envelope xmlns:s=""http://www.w3.org/2003/05/soap-envelope"" xmlns:a=""http://www.w3.org/2005/08/addressing""><s:Header><a:Action s:mustUnderstand=""1"">http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/Probe</a:Action><a:MessageID>urn:uuid:{0}</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand=""1"">urn:docs-oasis-open-org:ws-dd:ns:discovery:2009:01</a:To></s:Header><s:Body><Probe xmlns=""http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01""><d:Types xmlns:d=""http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01"" xmlns:dp0=""http://tempuri.org/"">dp0:IDiscoveryService</d:Types><Duration xmlns=""http://schemas.microsoft.com/ws/2008/06/discovery"">PT5S</Duration></Probe></s:Body></s:Envelope>";
string outgoingMessage = string.Format(outgoingMessageFormat, Guid.NewGuid().ToString());
return outgoingMessage;
}
private async Task SendDiscoveryMessage(DatagramSocket socket)
{
using (var stream = await socket.GetOutputStreamAsync(new HostName(DEST_IP_WSDISCOVERY), DEST_PORT_WSDISCOVERY))
{
string message = BuildDiscoveryMessage();
var data = Encoding.UTF8.GetBytes(message);
using (var writer = new DataWriter(stream))
{
writer.WriteBytes(data);
await writer.StoreAsync();
}
}
}
private void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
var dr = args.GetDataReader();
string message = dr.ReadString(dr.UnconsumedBufferLength);
_wsresponses.Add(new WSDiscoveryResponse(message, args.RemoteAddress, args.RemotePort));
}
}
UWP doesn’t support the WS-Discovery API for now. Details please see https://msdn.microsoft.com/en-us/library/windows/apps/mt185502.aspx.
There is no System.ServiceModel.Discovery API support for UWP apps in the document. But you can use it in a win32 application.
If you need this feature you can submit your idea to UserVoice site: https://wpdev.uservoice.com/forums/110705-universal-windows-platform
I don't know if I should answer my own question, but I think it may be useful for anyone trying to do the same, so here it goes.
Since WS-Discovery API is not available in UWP, I had to do it in another way. Using socket was the best alternative I could find. So every WS will listen to a specific port, awaiting for some broadcasted message searching for WS running in the LAN.
The WS implementation is win32, and this is the code needed:
private byte[] dataStream = new byte[1024];
private Socket serverSocket;
private void InitializeSocketServer(string id)
{
// Sets the server ID
this._id = id;
// Initialise the socket
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Initialise the IPEndPoint for the server and listen on port 30000
IPEndPoint server = new IPEndPoint(IPAddress.Any, 30000);
// Associate the socket with this IP address and port
serverSocket.Bind(server);
// Initialise the IPEndPoint for the clients
IPEndPoint clients = new IPEndPoint(IPAddress.Any, 0);
// Initialise the EndPoint for the clients
EndPoint epSender = (EndPoint)clients;
// Start listening for incoming data
serverSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epSender, new AsyncCallback(ReceiveData), epSender);
}
private void ReceiveData(IAsyncResult asyncResult)
{
// Initialise the IPEndPoint for the clients
IPEndPoint clients = new IPEndPoint(IPAddress.Any, 0);
// Initialise the EndPoint for the clients
EndPoint epSender = (EndPoint)clients;
// Receive all data. Sets epSender to the address of the caller
serverSocket.EndReceiveFrom(asyncResult, ref epSender);
// Get the message received
string message = Encoding.UTF8.GetString(dataStream);
// Check if it is a search ws message
if (message.StartsWith("SEARCHWS", StringComparison.CurrentCultureIgnoreCase))
{
// Create a response messagem indicating the server ID and it's URL
byte[] data = Encoding.UTF8.GetBytes($"WSRESPONSE;{this._id};http://{GetIPAddress()}:5055/wsserver");
// Send the response message to the client who was searching
serverSocket.BeginSendTo(data, 0, data.Length, SocketFlags.None, epSender, new AsyncCallback(this.SendData), epSender);
}
// Listen for more connections again...
serverSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epSender, new AsyncCallback(this.ReceiveData), epSender);
}
private void SendData(IAsyncResult asyncResult)
{
serverSocket.EndSend(asyncResult);
}
The client implementation is UWP. I've created the following class to do the search:
public class WSDiscoveryClient
{
public class WSEndpoint
{
public string ID;
public string URL;
}
private List<WSEndpoint> _endPoints;
private int port = 30000;
private int timeOut = 5; // seconds
/// <summary>
/// Get available Webservices
/// </summary>
public async Task<List<WSEndpoint>> GetAvailableWSEndpoints()
{
_endPoints = new List<WSEndpoint>();
using (var socket = new DatagramSocket())
{
// Set the callback for servers' responses
socket.MessageReceived += SocketOnMessageReceived;
// Start listening for servers' responses
await socket.BindServiceNameAsync(port.ToString());
// Send a search message
await SendMessage(socket);
// Waits the timeout in order to receive all the servers' responses
await Task.Delay(TimeSpan.FromSeconds(timeOut));
}
return _endPoints;
}
/// <summary>
/// Sends a broadcast message searching for available Webservices
/// </summary>
private async Task SendMessage(DatagramSocket socket)
{
using (var stream = await socket.GetOutputStreamAsync(new HostName("255.255.255.255"), port.ToString()))
{
using (var writer = new DataWriter(stream))
{
var data = Encoding.UTF8.GetBytes("SEARCHWS");
writer.WriteBytes(data);
await writer.StoreAsync();
}
}
}
private async void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Creates a reader for the incoming message
var resultStream = args.GetDataStream().AsStreamForRead(1024);
using (var reader = new StreamReader(resultStream))
{
// Get the message received
string message = await reader.ReadToEndAsync();
// Cheks if the message is a response from a server
if (message.StartsWith("WSRESPONSE", StringComparison.CurrentCultureIgnoreCase))
{
// Spected format: WSRESPONSE;<ID>;<HTTP ADDRESS>
var splitedMessage = message.Split(';');
if (splitedMessage.Length == 3)
{
var id = splitedMessage[1];
var url = splitedMessage[2];
_endPoints.Add(new WSEndpoint() { ID = id, URL = url });
}
}
}
}
}
Feel free to comment if you see something wrong, and please tell me if it helps you someway.
I am working on a transportation Project RailWay. Let me explain the project :there are a lot of sensors during the path of the train ,so when the train passes one of these sensors ,the sensor sends a value to CTC(A computer that manages the sensors) server the value is 1 or 0 ,1 means that the train arrive the sensor and 0 means the train left the sensor ,so every thing is ok ,now here is the scope of my project:
The CTC server send the value to MY-SERVER for example :ID=16(SENSOR-ID),state=0.it means that the train left the sensor that its id is 16 ,Note:That i know the location of sensors by id .so My problems start here : the CTC server sends its data by TCP ,so i have to create a listener to listen the data that comes from the CTC server ,(Note:Sometimes the data that comes from CTC is a lot and maybe some data be lost) ,I create a program using c# that listen the port but sometimes the data that coes fro CTC are lost why ?
So let me explain my programs:
It's the code that i wrote to get the data :
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3456);
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
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();
}
}
And here i call the server class :
class Program
{
static void Main(string[] args)
{
Server obj=new Server();
}
}
The CTC code that sends data is like this(An example) :
static void Main(string[] args)
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3456);
client.Connect(serverEndPoint);
using (NetworkStream clientStream = client.GetStream())
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");
clientStream.Write(buffer, 0, buffer.Length);
}
}
But sometimes my programs(SERVER CODE) lost data ?!!!Why ?Any idea ?
Best regards
Here is my solution of a basic Client/Server application using StreamReader and StreamWriter
Basic structure
The server will be running a TcpListener. We will use the Pending() method to check for waiting connections while not blocking the thread from exiting. When a new connection is waiting we will accept it with the AcceptTcpClient(), create a new instance of our own Client class and add it to a List<Client()> to mange it later. The class Client will store the methods to send data and hold informations like ID etc.
Code
Server Class:
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace CTCServer
{
class Server
{
//Stores the IP Adress the server listens on
private IPAddress ip;
//Stores the port the server listens on
private int port;
//Stores the counter of connected clients. *Note* The counter only gets increased, it acts as "id"
private int clientCount = 0;
//Defines if the server is running. When chaning to false the server will stop and disconnect all clients.
private bool running = true;
//Stores all connected clients.
public List<Client> clients = new List<Client>();
//Event to pass recived data to the main class
public delegate void GotDataFromCTCHandler(object sender, string msg);
public event GotDataFromCTCHandler GotDataFromCTC;
//Constructor for Server. If autoStart is true, the server will automaticly start listening.
public Server(IPAddress ip, int port, bool autoStart = false)
{
this.ip = ip;
this.port = port;
if (autoStart)
this.Run();
}
//Starts the server.
public void Run()
{
//Run in new thread. Otherwise the whole application would be blocked
new Thread(() =>
{
//Init TcpListener
TcpListener listener = new TcpListener(this.ip, this.port);
//Start listener
listener.Start();
//While the server should run
while (running)
{
//Check if someone wants to connect
if (listener.Pending())
{
//Client connection incoming. Accept, setup data incoming event and add to client list
Client client = new Client(listener.AcceptTcpClient(), this.clientCount);
//Declare event
client.internalGotDataFromCTC += GotDataFromClient;
//Add to list
clients.Add(client);
//Increase client count
this.clientCount++;
}
else
{
//No new connections. Sleep a little to prevent CPU from going to 100%
Thread.Sleep(100);
}
}
//When we land here running were set to false or another problem occured. Stop server and disconnect all.
Stop();
}).Start(); //Start thread. Lambda \(o.o)/
}
//Fires event for the user
private void GotDataFromClient(object sender, string data)
{
//Data gets passed to parent class
GotDataFromCTC(sender, data);
}
//Send string "data" to all clients in list "clients"
public void SendToAll(string data)
{
//Call send method on every client. Lambda \(o.o)/
this.clients.ForEach(client => client.Send(data));
}
//Stop server
public void Stop()
{
//Exit listening loop
this.running = false;
//Disconnect every client in list "client". Lambda \(o.o)/
this.clients.ForEach(client => client.Close());
//Clear clients.
this.clients.Clear();
}
}
}
Client Class
using System.IO;
using System.Net.Sockets;
using System.Threading;
namespace CTCServer
{
class Client
{
//Stores the TcpClient
private TcpClient client;
//Stores the StreamWriter. Used to write to client
private StreamWriter writer;
//Stores the StreamReader. Used to recive data from client
private StreamReader reader;
//Defines if the client shuld look for incoming data
private bool listen = true;
//Stores clientID. ClientID = clientCount on connection time
public int id;
//Event to pass recived data to the server class
public delegate void internalGotDataFromCTCHandler(object sender, string msg);
public event internalGotDataFromCTCHandler internalGotDataFromCTC;
//Constructor
public Client(TcpClient client, int id)
{
//Assain members
this.client = client;
this.id = id;
//Init the StreamWriter
writer = new StreamWriter(this.client.GetStream());
reader = new StreamReader(this.client.GetStream());
new Thread(() =>
{
Listen(reader);
}).Start();
}
//Reads data from the connection and fires an event wih the recived data
public void Listen(StreamReader reader)
{
//While we should look for new data
while(listen)
{
//Read whole lines. This will read from start until \r\n" is recived!
string input = reader.ReadLine();
//If input is null the client disconnected. Tell the user about that and close connection.
if (input == null)
{
//Inform user
input = "Client with ID " + this.id + " disconnceted.";
internalGotDataFromCTC(this, input);
//Close
Close();
//Exit thread.
return;
}
internalGotDataFromCTC(this, input);
}
}
//Sends the string "data" to the client
public void Send(string data)
{
//Write and flush data
writer.WriteLine(data);
writer.Flush();
}
//Closes the connection
public void Close()
{
//Stop listening
listen = false;
//Close streamwriter FIRST
writer.Close();
//Then close connection
client.Close();
}
}
}
Test code. Note: this is a console application!
using System;
using System.Net;
namespace CTCServer
{
class Program
{
static void Main(string[] args)
{
//Set title
Console.Title = "CTC-Server";
//Create new instance of the server
Server server = new Server(IPAddress.Any, 1221);
//Handle GotDataFromCTC
server.GotDataFromCTC += GotDataFromCTC;
//Start the server. We could use the autoStart in constructor too.
server.Run();
//Inform about the running server
Console.WriteLine("Server running");
//Listen for input.
while(true)
{
//Read input line from cmd
string input = Console.ReadLine();
//Stores the command itself
string command;
//Stores parameters
string param = "";
//If input line contains a whitespace we have parameters that need to be processed.
if(input.Contains(" "))
{
//Split the command from the parameter. Parte before whitespace = command, rest = parameters
command = input.Split(' ')[0];
param = input.Substring(command.Length +1);
}
else
{
//No whitespace, so we dont have any parameters. Use whole input line as command.
command = input;
}
//Process the command
switch(command)
{
//Sends a string to all clients. Everything behind "send " (Note the whitespace) will be send to the client. Exanple "send hello!" will send "hello!" to the client.
case "send":
{
//Give some feedback
Console.WriteLine("Send to all clients: {0}", param);
//Send data
server.SendToAll(param);
//Done
break;
}
//Closes connection to all clients and exits. No parameters.
case "exit":
{
//Stop the server. This will disconncet all clients too.
server.Stop();
//Clean exit
Environment.Exit(0);
//Done. We wont get here anyway.
break;
}
}
}
}
//Recived data from clien. Show it!
static void GotDataFromCTC(object sender, string data)
{
Console.WriteLine("Data from CTC-Server with ID {0} recived:\r\n{1}", (sender as Client).id, data);
}
}
}
NOTE that this application doesnt have any exception handling. I did this to show a direction, you will need to modify the code to fit to your requirements. Let me know if you need something.
Example Project (Visual Studio 2013 Pro): Download | Virustoal
I found an article about Socket programming that using StreamReader ,It using one thread ,and no information lost is happened
You can take a look here :
http://www.codeproject.com/Articles/511814/Multi-client-per-one-server-socket-programming-in
My first question here. I am new to this kind of programming, and i've only programmed .NET web sites and forms.
Now, the company I work at, asks me to make an ActiveX component, that listens to UDP messages, and turns them into events.
The UDP msgs are send from Avaya system, so i was told that to test my ActiveX, at first I need to create an app, that only sends UDP (only one button that sends pre-defined UDP string). And then create listener socket, ordinary C# app, that will get those transmitted UDP string from the tests app. Both apps will work on the same machine.
Later, when i get this working, i need to make the listener an ActiveX component, but first things first.
I need to know if there are any good tutorials about this, and any idea on how to start? I am sorry for my ignorance, but i am really new on this and i don't really have any time to learn this since it has to be done in 2 weeks.
Thanks in advance.
edit: I managed to create 2 simple console applications, and was sending UDP messages between them successfully. The sender will be only for testing, and now I need to re-make my receiver to get the UDP message and 'translate' it to events. And lastly, to make it an ActiveX control...
Simple server and client:
public struct Received
{
public IPEndPoint Sender;
public string Message;
}
abstract class UdpBase
{
protected UdpClient Client;
protected UdpBase()
{
Client = new UdpClient();
}
public async Task<Received> Receive()
{
var result = await Client.ReceiveAsync();
return new Received()
{
Message = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length),
Sender = result.RemoteEndPoint
};
}
}
//Server
class UdpListener : UdpBase
{
private IPEndPoint _listenOn;
public UdpListener() : this(new IPEndPoint(IPAddress.Any,32123))
{
}
public UdpListener(IPEndPoint endpoint)
{
_listenOn = endpoint;
Client = new UdpClient(_listenOn);
}
public void Reply(string message,IPEndPoint endpoint)
{
var datagram = Encoding.ASCII.GetBytes(message);
Client.Send(datagram, datagram.Length,endpoint);
}
}
//Client
class UdpUser : UdpBase
{
private UdpUser(){}
public static UdpUser ConnectTo(string hostname, int port)
{
var connection = new UdpUser();
connection.Client.Connect(hostname, port);
return connection;
}
public void Send(string message)
{
var datagram = Encoding.ASCII.GetBytes(message);
Client.Send(datagram, datagram.Length);
}
}
class Program
{
static void Main(string[] args)
{
//create a new server
var server = new UdpListener();
//start listening for messages and copy the messages back to the client
Task.Factory.StartNew(async () => {
while (true)
{
var received = await server.Receive();
server.Reply("copy " + received.Message, received.Sender);
if (received.Message == "quit")
break;
}
});
//create a new client
var client = UdpUser.ConnectTo("127.0.0.1", 32123);
//wait for reply messages from server and send them to console
Task.Factory.StartNew(async () => {
while (true)
{
try
{
var received = await client.Receive();
Console.WriteLine(received.Message);
if (received.Message.Contains("quit"))
break;
}
catch (Exception ex)
{
Debug.Write(ex);
}
}
});
//type ahead :-)
string read;
do
{
read = Console.ReadLine();
client.Send(read);
} while (read != "quit");
}
}
Simple server and client:
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
class Program
{
static void Main(string[] args)
{
// Create UDP client
int receiverPort = 20000;
UdpClient receiver = new UdpClient(receiverPort);
// Display some information
Console.WriteLine("Starting Upd receiving on port: " + receiverPort);
Console.WriteLine("Press any key to quit.");
Console.WriteLine("-------------------------------\n");
// Start async receiving
receiver.BeginReceive(DataReceived, receiver);
// Send some test messages
using (UdpClient sender1 = new UdpClient(19999))
sender1.Send(Encoding.ASCII.GetBytes("Hi!"), 3, "localhost", receiverPort);
using (UdpClient sender2 = new UdpClient(20001))
sender2.Send(Encoding.ASCII.GetBytes("Hi!"), 3, "localhost", receiverPort);
// Wait for any key to terminate application
Console.ReadKey();
}
private static void DataReceived(IAsyncResult ar)
{
UdpClient c = (UdpClient)ar.AsyncState;
IPEndPoint receivedIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receivedBytes = c.EndReceive(ar, ref receivedIpEndPoint);
// Convert data to ASCII and print in console
string receivedText = ASCIIEncoding.ASCII.GetString(receivedBytes);
Console.Write(receivedIpEndPoint + ": " + receivedText + Environment.NewLine);
// Restart listening for udp data packages
c.BeginReceive(DataReceived, ar.AsyncState);
}
}
Server
public void serverThread()
{
UdpClient udpClient = new UdpClient(8080);
while(true)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
lbConnections.Items.Add(RemoteIpEndPoint.Address.ToString()
+ ":" + returnData.ToString());
}
}
And initialize the thread
private void Form1_Load(object sender, System.EventArgs e)
{
Thread thdUDPServer = new Thread(new ThreadStart(serverThread));
thdUDPServer.Start();
}
Client
private void button1_Click(object sender, System.EventArgs e)
{
UdpClient udpClient = new UdpClient();
udpClient.Connect(txtbHost.Text, 8080);
Byte[] senddata = Encoding.ASCII.GetBytes("Hello World");
udpClient.Send(senddata, senddata.Length);
}
Insert it to button command.
Source: http://technotif.com/creating-simple-udp-server-client-transfer-data-using-c-vb-net/
hey all,
I have made a socket server in C# for a flash game that I am developing, I got the code from somewhere and I am a beginner in c# and .net development . It works fine in practice when connections are made and the server functions correctly. Get 2 concurrent connections at the same time and we have a problem.
here is the basic aspects of the socket server below: (alot taken out for obvious reasons)
how can I alter this so that it can handle concurrent connections? Should I be threading each response?
Thanks
class TcpSock
{
int tcpIndx = 0;
int tcpByte = 0;
byte[] tcpRecv = new byte[1024];
////////////////////////////////////////
public Socket tcpSock;
////////////////////////////////////////
public int Recv(ref string tcpRead)
{
tcpByte = tcpSock.Available;
if (tcpByte > tcpRecv.Length - tcpIndx)
tcpByte = tcpRecv.Length - tcpIndx;
tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte,
SocketFlags.Partial);
tcpRead = Encoding.ASCII.GetString
(tcpRecv, tcpIndx, tcpByte);
tcpIndx += tcpByte;
return tcpRead.Length;
}
public int RecvLn(ref string tcpRead)
{
tcpRead = Encoding.ASCII.GetString
(tcpRecv, 0, tcpIndx);
tcpIndx = 0;
return tcpRead.Length;
}
public int Send(string tcpWrite)
{
return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite));
}
public int SendLn(string tcpWrite)
{
return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n"));
}
}
[STAThread]
static void Main()
{
Thread Server1 = new Thread(RunServer);
Server1.Start();
}
static void RunServer()
{
///class IPHostEntry : Stores information about the Host and is required
///for IPEndPoint.
///class IPEndPoint : Stores information about the Host IP Address and
///the Port number.
///class TcpSock : Invokes the constructor and creates an instance.
///class ArrayList : Stores a dynamic array of Client TcpSock objects.
IPHostEntry Iphe = Dns.Resolve(Dns.GetHostName());
IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444);
Socket Server = new Socket(Ipep.Address.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
///Initialize
///Capacity : Maximux number of clients able to connect.
///Blocking : Determines if the Server TcpSock will stop code execution
///to receive data from the Client TcpSock.
///Bind : Binds the Server TcpSock to the Host IP Address and the Port Number.
///Listen : Begin listening to the Port; it is now ready to accept connections.
ArrayList Client = new ArrayList();
string[,] Users = new string[1000,9];
string rln = null;
string[] Data;
Client.Capacity = 1000;
Server.Blocking = false;
Server.Bind(Ipep);
Server.Listen(32);
Console.WriteLine("Server 1 {0}: listening to port {1}", Dns.GetHostName(), Ipep.Port);
////////////////////////////////////////////////////////////////////////////////////////////
///Main loop
///1. Poll the Server TcpSock; if true then accept the new connection.
///2. Poll the Client TcpSock; if true then receive data from Clients.
while (true)
{
//Accept - new connection
#region new connection
if (Server.Poll(0, SelectMode.SelectRead))
{
int i = Client.Add(new TcpSock());
((TcpSock)Client[i]).tcpSock = Server.Accept();
Console.WriteLine("Client " + i + " connected.");
Users[i, 0] = i.ToString();
}
#endregion
for (int i = 0; i < Client.Count; i++)
{
//check for incoming data
if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead))
{
//receive incoming data
if (((TcpSock)Client[i]).Recv(ref rln) > 0)
{
Console.WriteLine(rln.ToString());
Data = rln.Split('|');
// 1) initial connection
#region InitialConnection
if (Data[0] == "0000")
{
}
}
}
}
}
}
You will need to not use synchronous functions but asynchrounus functions like Socket.BeginReceive
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
public static partial class TcpServer
{
public static void Main()
{
// Setup listener on "localhost" port 12000
IPAddress ipAddr = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddr, 12000);
server.Start(); // Network driver can now allow incoming requests
// Accept up to 1 client per CPU simultaneously
Int32 numConcurrentClients = Environment.ProcessorCount;
for (Int32 n = 0; n
private static Byte[] ProcessData(Byte[] inputData)
{
String inputString = Encoding.UTF8.GetString(inputData, 1, inputData[0]);
String outputString = inputString.ToUpperInvariant();
Console.WriteLine("Input={0}", inputString);
Console.WriteLine(" Output={0}", outputString);
Console.WriteLine();
Byte[] outputStringBytes = Encoding.UTF8.GetBytes(outputString);
Byte[] outputData = new Byte[1 + outputStringBytes.Length];
outputData[0] = (Byte)outputStringBytes.Length;
Array.Copy(outputStringBytes, 0, outputData, 1, outputStringBytes.Length);
return outputData;
}
}
public static partial class TcpServer
{
private sealed class ClientConnectionApm
{
private TcpListener m_server;
private TcpClient m_client;
private Stream m_stream;
private Byte[] m_inputData = new Byte[1];
private Byte m_bytesReadSoFar = 0;
public ClientConnectionApm(TcpListener server)
{
m_server = server;
m_server.BeginAcceptTcpClient(AcceptCompleted, null);
}
private void AcceptCompleted(IAsyncResult ar)
{
// Connect to this client
m_client = m_server.EndAcceptTcpClient(ar);
// Accept another client
new ClientConnectionApm(m_server);
// Start processing this client
m_stream = m_client.GetStream();
// Read 1 byte from client which contains length of additional data
m_stream.BeginRead(m_inputData, 0, 1, ReadLengthCompleted, null);
}
private void ReadLengthCompleted(IAsyncResult result)
{
// If client closed connection; abandon this client request
if (m_stream.EndRead(result) == 0) { m_client.Close(); return; }
// Start to read 'length' bytes of data from client
Int32 dataLength = m_inputData[0];
Array.Resize(ref m_inputData, 1 + dataLength);
m_stream.BeginRead(m_inputData, 1, dataLength, ReadDataCompleted, null);
}
private void ReadDataCompleted(IAsyncResult ar)
{
// Get number of bytes read from client
Int32 numBytesReadThisTime = m_stream.EndRead(ar);
// If client closed connection; abandon this client request
if (numBytesReadThisTime == 0) { m_client.Close(); return; }
// Continue to read bytes from client until all bytes are in
m_bytesReadSoFar += (Byte)numBytesReadThisTime;
if (m_bytesReadSoFar
private void WriteDataCompleted(IAsyncResult ar)
{
// After result is written to client, close the connection
m_stream.EndWrite(ar);
m_client.Close();
}
}
}
First of all: Stop using non-blocking sockets. In .NET you should either stick to the synchronous methods Receive/Send or asynchronous methods BeginReceive/BeginSend.
You should only stick with sync methods if you will have only a handful of clients. Then launch each new client in a new thread. This is the easiest option to get everthing running.
Simply do like this:
public void AcceptClients()
{
TcpListener listener = new TcpListener(IPAddress.Any, 5566);
listener.Start();
while (_serverRunning)
{
var socket = listener.AcceptSocket();
new Thread(ClientFunc).Start(socket);
}
}
public void ClientFun(object state)
{
var clientSocket = (Socket)state;
var buffer = new byte[65535];
while (_serverRunning)
{
//blocking read.
clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
//check packet.
// handle packet
// send respons.
clientSocket.Send(alalalal);
}
}
You should refactor the methods so that they follow SRP. The code is just a small guide to get you going.