I have a number of C# software applications that are add-ins for a peice of software that has a .net API.
for software licensing purposes I'm required to have a license server. I've got this, at the moment this is what it does:
when a tool is run, it contacts the license server with its computer name and username
the server recieves this request, logs the request, and checks to see if the number of requests from that machien and or user have exceeded the preconfigured maximum (2 different licensing types)
it does this using an encrypted file which lists the time, machine name, username etc
if its ok, it returns OKAY response to the computer and the tool then runs
if it doesnt return anything or if it returns a not OK response the tool will not run (the software only runs for a short time, but is regulary ran, as opposed to opening for a long time)
This works great, except I'm having a problem that the server randomly crashes, and users can't get onto it.
This is the first client-server app I've done and I'm a bit in the dark (and feel like I'm re-inventing something which is commonly used), is there any good guides for creating something like that? My apps is very simple, I have a service running on the server looping listening on a TCP port, waiting for something to be sent.
public void StartListening()
{
Listening = true;
// Set the TcpListener on port 41616.
Int32 port = 41616;
IPAddress localAddr = IPAddress.Any;
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
Listen();
}
public void Listen()
{
try
{
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
while (Listening)
{
TcpClient client = server.AcceptTcpClient();
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
string returnData;
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = null;// DO STUFF BASED ON DATA
// set returnData to be the response (ie OKAY)
msg = System.Text.Encoding.ASCII.GetBytes(returnData);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", returnData);
// Shutdown and end connection
client.Close();
}
}
catch (Exception ex)
{
//LOG ERROR
}
finally
{
Listening = false;
server.Stop();
}
}
I have a feeling the server is hanging somewhere on the decryption /encryption of the license log, as the server runs fine for a while then just stops, and if i re-create the license log it works. But thats not the point of this post (though any tips on why I'm getting this error:
Error occured: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at BWSSLicenseServer.LicenseServer.Listen()
woudl be great)
My question is - how do I debug this easily in .NET? is there any good guides out there to help me? or is there any free framework for this? Should I be doing this code a totally different way (WCF, Web Service or something like that?)
ended up using CryptoLicensing as suggested in the comments
It may be something to do with the object expiring. Try adding this to your server class:
public override object InitializeLifetimeService()
{
return null;
}
Related
I've got a little problem with the .Net Sockets in C#.
I programmed a client and a server working with TCP.
As the client is opened it sends a handshake to the server. The server answers with it's state (clientexists, clientaccepted,...). After that the application sends a getdata-request, abandons the connection and listens for the server's 'response'. Now, the server builds a connection to the client and sends all the data the client needs.
The code and everything else works, but the problem:
On our company testserver it works fine, on the live server only the handshake works. After it the client doesn't receive any more data. Serverapplication is the same on both servers.
I thought the problem was caused by some firewall (server wants to build a tcp connection to the client -> not good), but the system administrator said there is no firewall that could block that.
Now I'm searching for a ('cheap') solution that doesn't take too much time and changes in code. If anyone knows how to theoretically solve that, that would be great.
BTW: I am not allowed to do anything on the live server other than run the serverapplication. I don't have the possibility to debug on this server.
I can't publish all of my code, but if you need to see specific parts of it, ask for it please.
---EDIT---
Client-Server communication
1) Client startup
Client send handshake (new tcp connection)
2) Server validates handshake and saves IP
Server responds with it's client state (same tcp connection)
3) Client acknowledges this response and abandons this connection
Client sends getdata-request (new tcp connection)
Client abandons this tcp connection, too
4) Server receives getdata-request and collects the needed data in the main database
Server sends all the collected data to the client (multiple tcp connections)
5) Client receives all data and displays it in it's GUI (multiple tcp connections and the order of the data is kept by working with AutoResetEvents and Counts of sockets to send)
This is the main part my code does. It's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too.
Another thing i forgot to mention is that the solution uses two Ports '16777' and '16778'. One to receive/listen and one to send.
My code is based on the MSDN example of the asynchronous server and client.
Sending a handshake (and getdata-request)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
Server listener
public void StartListening()
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(System.Int32.MaxValue);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
Socket send
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
Socket send all data part (answer to getdata-request | socToHandle should be the socket of the previous connection of the getdata-request)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
Looking through my old code I have one idea =>
Could I send everything over the same connection by changing:
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
(which creates a new connection) to something that uses the same connection?
If that would work, how can I do that?
And would the listener part of the client still receive single packets?
Servers and their environment are configured to handle incoming requests properly. Clients are usually behind a router, which by default make them unable to receive incoming connections from outside their network (a good thing).
To enable incoming connections, you could configure your router to forward all requests for a certain port number to your machine. No one else on your network would be able to run the client then, though.
This is why in a typical multiple clients-single server environment, the client makes all the connections, and only the server requires any changes to the network landscape.
I don't know why you chose to connect to the clients from the server side, but I would strongly advise against this - any cheap solution that uses this mechanism may turn out to be very expensive in the end.
I've been looking around for the answer without luck. The program is a simple chat app that either listens or talks. The connection is established between the client and server, but when I send a message, the other does not seem to recieve it.
server waiting for connection
private void ListenForConnection(IPAddress ipAddress)
{
tcpListener = new TcpListener(ipAddress, portNumber);
tcpListener.Start();
client = tcpListener.AcceptTcpClient();
stream = client.GetStream();
stream.ReadTimeout = 200;
}
client connecting
private void EstablishConnection(IPAddress ipAddress)
{
client = new TcpClient();
client.Connect(ipAddress, portNumber);
stream = client.GetStream();
stream.ReadTimeout = 200;
}
client writing a message
public void SendMessage(String message)
{
StreamWriter networkWriter = new StreamWriter(stream);
networkWriter.Write(message);
networkWriter.Flush();
}
server reading a message
public String ListenForMessage()
{
String networkRead = String.Empty;
try
{
networkRead = new StreamReader(stream).ReadToEnd();
}
catch (Exception e) { }
return networkRead;
}
The send and recieve are identical for server and client. I intend to add error handling more when the messages are working.
I'm wondering that possibly there is an issue with my connection. Currently I am running 2 instances of the chat program on my machine, one server one client. The client connects at 127.0.0.1 (localhost) on port 8080 when the server is listening to port 8080. However the client does not connect at 192.168.1.100, which is my computer's actual ip, not sure if that might indicate something.
EDIT: adjusted the write and read to use stream writer and reader and flush
1.First of all , I will suggest you to make sure that your connection has been really established between your client and server.
2.Secondly, I will suggest you to flush your stream after you write, there are cache mechanism built in Stream, write to stream doesn't mean it will be send across the wire immediately.
3.It is a good way to learn networking in this way, but if you are creating commercial product, I will suggest you to look for some mature open source components.
We have a device that accepts ascii messages over a wireless network, and then responds with a value and I have successfully implemented this in a Windows Forms 2010 solution in c#.
I wrote this as a test solution to prove the technology and the actual calls to the device will be made on a Motorola MC55 handheld device.
I have now written an additional test solution in Visual Studio 2008 and installed this onto a device, but the connection to the TcpClient takes around 30 seconds every time its called on the mobile device, where as on the windows solution it's almost instant.
This is far too slow, so I have started looking at reusing the TcpClient, but not had any success and wondered if anyone else has had similar issues and to ask how they got around it, or if anyone can offer any advice on how to reuse a TcpClient so I don't have to create a new one every time I want to make my call.
The code for the connection is shown below...
public static string GetValueFromDevice(string deviceIPAddress, int devicePort, string messageSentToDevice)
{
string returnValue = "";
try
{
TcpClient client = new TcpClient(deviceIPAddress, devicePort);
byte[] inData = System.Text.Encoding.ASCII.GetBytes(messageSentToDevice);
NetworkStream stream = client.GetStream();
stream.Write(inData, 0, inData.Length);
byte[] outData = new Byte[256];
int bytes = stream.Read(outData, 0, outData.Length);
returnValue = System.Text.Encoding.ASCII.GetString(outData, 0, bytes);
stream.Close();
client.Close();
}
catch (Exception ex)
{
returnValue = ex.Message;
}
return returnValue;
}
You can leave the TcpClient open as long as you like. Keep the client and stream variables as part of the class (instead of in the function), and don't call Close() until you're done.
You can persist and re-use the client and stream and place the code into a separate thread.
But, I do not believe the client needs about 30 seconds to initialize. I see that slow init for TCP client when having an ActiveSync connection, but if you have a wireless only connection, it should init immediately.
So also check your network setup. After first VS deploy and debug session using Active Sync, Visual Studio is able to re-use the determined wireless IP address and runs subsequent deploy/debug sessions via the wireless TCP/IP (if ActiveSync on PC is set to allow Data connections during AS connections).
I was looking how to detect a 'client disconnect' when using a TcpListener.
All the answers seem to be similar to this one:
TcpListener: How can I detect a client disconnect?
Basically, read from the stream and if Read() returns 0 the client had disconnected.
But that's assuming that a client disconnects after every single stream of data it sent.
We operate in environments where the TCP connect/disconnect overhead is both slow and expensive.
We establish a connection and then we send a number of requests.
Pseudocode:
client.Connect();
client.GetStatus();
client.DoSomething();
client.DoSomethingElse();
client.AndSoOn();
client.Disconnect();
Each call between Connect and Disconnect() sends a stream of data to the server.
The server knows how to analyze and process the streams.
If let the TcpListener read in a loop without ever disconnecting it reads and handles all the messages, but after the client disconnects, the server has no way of knowing that and
it will never release the client and accept new ones.
var read = client.GetStream().Read(buffer, 0, buffer.Length);
if (read > 0)
{
//Process
}
If I let the TcpListener drop the client when read == 0 it only accepts
the first stream of data only to drop the client immediately after.
Of course this means new clients can connect.
There is no artificial delay between the calls,
but in terms of computer time the time between two calls is 'huge' of course,
so there will always be a time when read == 0 even though that does not mean
the client has or should be disconnected.
var read = client.GetStream().Read(buffer, 0, buffer.Length);
if (read > 0)
{
//Process
}
else
{
break; //Always executed as soon as the first stream of data has been received
}
So I'm wondering... is there a better way to detect if the client has disconnected?
You could get the underlying socket using the NetworkStream.Socket property and use it's Receive method for reading.
Unlike NetworkStream.Read, the linked overload of Socket.Receive will block until the specified number of bytes have been read, and will only return zero if the remote host shuts down the TCP connection.
UPDATE: #jrh's comment is correct that NetworkStream.Socket is a protected property and cannot be accessed in this context. In order to get the client Socket, you could use the TcpListener.AcceptSocket method which returns the Socket object corresponding to the newly established connection.
Eren's answer solved the problem for me. In case anybody else is facing the same issue
here's some 'sample' code using the Socket.Receive method:
private void AcceptClientAndProcess()
{
try
{
client = server.Accept();
client.ReceiveTimeout = 20000;
}
catch
{
return;
}
while (true)
{
byte[] buffer = new byte[client.ReceiveBufferSize];
int read = 0;
try
{
read = client.Receive(buffer);
}
catch
{
break;
}
if (read > 0)
{
//Handle data
}
else
{
break;
}
}
if (client != null)
client.Close(5000);
}
You call AcceptClientAndProcess() in a loop somewhere.
The following line:
read = client.Receive(buffer);
will block until either
Data is received, (read > 0) in which case you can handle it
The connection has been closed properly (read = 0)
The connection has been closed abruptly (An exception is thrown)
Either of the last two situations indicate the client is no longer connected.
The try catch around the Socket.Accept() method is also required
as it may fail if the client connection is closed abruptly during the connect phase.
Note that did specify a 20 second timeout for the read operation.
The documentation for NetworkStream.Read does not reflect this, but in my experience, 'NetworkStream.Read' blocks if the port is still open and no data is available, but returns 0 if the port has been closed.
I ran into this problem from the other side, in that NetworkStream.Read does not immediately return 0 if no data is currently available. You have to use NetworkStream.DataAvailable to find out if NetworkStream.Read can read data right now.
How do I go about making a socket policy file server in C#. All it has to do is listen on port 843 for the string "<policy-file-request/>" followed by a NULL byte and then return an XML string (which is the socket policy file).
I haven't coded this sort of thing before and am unsure of where to start. Do I create it in a windows service? Any tips or links are welcome.
Background:
To contact a web service from flash I am using the 'as3httpclient' library instead of the URLRequest/URLLoader. This is because it gives me the ability to send custom headers with GET requests. This library uses low-level sockets to do its stuff.
When flash uses low-level sockets to connect to a server it looks for a socket policy file - and this needs to be served up by a socket policy file server.
Socket Policy File Article from Adobe
A few things to be aware of using your suggested architecture:
Trying to send an HTTP request over sockets
Principally, you need to be aware that even though you can chat http at a lower level using sockets, there are a large number of cases where communication in this fashion will fail. Mainly these failures will occur if the user has a proxy server enabled in their browser, as there is no effective means of discovering and subsequently using the proxy when connecting via a socket.
In order to make a policy server, you can use the TcpListener class. You would start listening as follows:
var tcpListener = new TcpListener(IPAddress.Any, 843 );
tcpListener.start();
tcpListener.BeginAcceptTcpClient(new AsyncCallback(NewClientHandler), null);
The method NewClientHandler would have the form:
private void NewClientHandler(IAsyncResult ar)
{
TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
...
At which point you might want to supply the tcpClient object to a class of your own creation to handle the validation of the data coming from the socket. I'm going to call it RemoteClient.
In RemoteClient, you'd have something like this:
var buffer=new byte[BUFFER_SIZE];
tcpClient.GetStream().BeginRead(buffer, 0, buffer.Length, Receive, null);
and a Receive method:
private void Receive(IAsyncResult ar)
{
int bytesRead;
try
{
bytesRead = tcpClient.GetStream().EndRead(ar);
}
catch (Exception e)
{
//something bad happened. Cleanup required
return;
}
if (bytesRead != 0)
{
char[] charBuffer = utf8Encoding.GetChars(buffer, 0, bytesRead);
try
{
tcpClient.GetStream().BeginRead(buffer, 0, buffer.Length, Receive, null);
}
catch (Exception e)
{
//something bad happened. Cleanup required
}
}
else
{
//socket closed, I think?
return;
}
}
and some send methods:
public void Send(XmlDocument doc)
{
Send(doc.OuterXml);
}
private void Send(String str)
{
Byte[] sendBuf = utf8Encoding.GetBytes(str);
Send(sendBuf);
}
private void Send(Byte[] sendBuf)
{
try
{
tcpClient.GetStream().Write(sendBuf, 0, sendBuf.Length);
tcpClient.GetStream().WriteByte(0);
tcpClient.GetStream().WriteByte(13); //very important to terminate XmlSocket data in this way, otherwise Flash can't read it.
}
catch (Exception e)
{
//something bad happened. cleanup?
return;
}
}
That's all the important details I think. I wrote this some time ago... the Receive method looks like it could do with a rework, but it should be enough to get you started.
Create a listening socket.
When a connection is opened, perform a receive and wait for the expected string. When received send the file content and then close the socket.
Wrap this in a service (running as a low privilege account).
Most of the work is done with the System.Net.Sockets.Socket class, the documentation contains a sample, The API is very similar to the BSD socket API overall (largely there is a 1:1 mapping from BSD API to Socket (or help type) method) so any background should be easily translatable.
I had to to this task with both Java and C#, they are quite similar.
You can have a look at java policy file.
Some issue can see at this answer: https://stackoverflow.com/a/12854204/1343667