I'm trying to create a windows service that needs to run in the background and listen for incoming traffic (a normal and regular TCP listener)
my code is:
private TcpListener server;
public void startServer()
{
// EventLog.WriteEntry(source, "connected on: " + ipAddress.ToString() + " port: " + Service1.Port.ToString());
server = new TcpListener(IPAddress.Parse("127.0.0.1"), Service1.Port);
server.Start();
while (true)
{
var client = server.AcceptTcpClient();
new Thread(work).Start(client);
}
public void work(object client)
{
string msg = null;
var clientLocal = (TcpClient)client;
using (NetworkStream ns = clientLocal.GetStream())
using (StreamReader sr = new StreamReader(ns))
{
byte[] msgFullArray = new UTF8Encoding(true).GetBytes(msg);
fs.Write(msgFullArray, 0, msg.Length);
}
now if you don't look at the work method at all as whenever i start my service it freezes whenever i try to start it at my :
var client = server.AcceptTcpClient();
meaning my service never gets to use the Thread or my Work method..
i can see from previous logging that it enters my while loop and then just times out the service
In your OnStart Method you have to instantiate a server class.
protected override void OnStart(string[] args)
{
// Create the Server Object ans Start it.
server = new TCPServer();
server.StartServer();
}
that is responsible to handle the connections to the server by creating a new Thread (so that it is a non-blocking process)
public void StartServer()
{
if (m_server!=null)
{
// Create a ArrayList for storing SocketListeners before
// starting the server.
m_socketListenersList = new ArrayList();
// Start the Server and start the thread to listen client
// requests.
m_server.Start();
m_serverThread = new Thread(new ThreadStart(ServerThreadStart));
m_serverThread.Start();
// Create a low priority thread that checks and deletes client
// SocktConnection objcts that are marked for deletion.
m_purgingThread = new Thread(new ThreadStart(PurgingThreadStart));
m_purgingThread.Priority=ThreadPriority.Lowest;
m_purgingThread.Start();
}
}
for each socket that it will be listening by a TCPListener.
private void ServerThreadStart()
{
// Client Socket variable;
Socket clientSocket = null;
TCPSocketListener socketListener = null;
while(!m_stopServer)
{
try
{
// Wait for any client requests and if there is any
// request from any client accept it (Wait indefinitely).
clientSocket = m_server.AcceptSocket();
// Create a SocketListener object for the client.
socketListener = new TCPSocketListener(clientSocket);
// Add the socket listener to an array list in a thread
// safe fashon.
//Monitor.Enter(m_socketListenersList);
lock(m_socketListenersList)
{
m_socketListenersList.Add(socketListener);
}
//Monitor.Exit(m_socketListenersList);
// Start a communicating with the client in a different
// thread.
socketListener.StartSocketListener();
}
catch (SocketException se)
{
m_stopServer = true;
}
}
}
Here it is the full project article.
Related
I'm working on a desktop application that involves a TcpListener.
I'm attempting to create the TcpListener and handle clients in a background thread...
private TcpListener _listener;
public MainWindow()
{
InitializeComponent();
DataContext = _vm;
Thread smtpThread = new Thread(new ThreadStart(StartSmtpLocal));
smtpThread.Start();
}
void StartSmtpLocal()
{
_listener = new TcpListener(IPAddress.Any, 1025);
_listener.Start();
while (true)
{
Console.WriteLine("Waiting for connection...");
TcpClient client = _listener.AcceptTcpClient();
Console.WriteLine($"Client status: {client.Connected}"); // This is 'Client status: True'
SMTPServer handler = new SMTPServer();
handlers.Add(handler);
handler.Initialize(client, SmtpMessageComplete);
Thread thread = new Thread(new ThreadStart(handler.Run));
thread.Start();
}
}
My SMTPServer.Initialize method is simply storing a reference to the TcpClient.
private TcpClient _client;
private Action<MimeMessage> _finishAction;
private MimeMessage _messageRead;
public void Initialize(TcpClient client, Action<MimeMessage> finishAction)
{
_client = client;
_finishAction = finishAction;
}
And Run would process messages from the client. However immediately upon entering Run in the new thread, the client is disconnected.
public void Run()
{
Write("220 localhost -- Fake proxy server");
Console.WriteLine($"Client status {_client.Connected}"); // This is 'Client status False'
...
}
Any ideas on what is causing the client to disconnect here?
Thanks!
I am trying to write a TCP listener that can connect to multiple clients and send and receive data.
Some of my code -
Calling server -
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'cresijCamDataSet1.CentralControl' table. You can move, or remove it, as needed.
this.centralControlTableAdapter1.Fill(this.cresijCamDataSet1.CentralControl);
s = new Server();
Thread th = new Thread(s.Run);
th.Start();
}
Run Method -
public async void Run()
{
tcp = new TcpListener(IPAddress.Any, 1200);
tcp.Start();
while (true)
{
try
{
TcpClient client = await tcp.AcceptTcpClientAsync();
Thread th = new Thread(()=>{
Process(client);
}) ;
}
catch (Exception ex)
{
string m = ex.Message;
}
}
}
private async Task Process(TcpClient tcpClient)
{
bool hasItem = clients.Contains(tcpClient);
if(hasItem == false)
{
clients.Add(tcpClient);
}
IPEndPoint iPEndPoint =(IPEndPoint) tcpClient.Client.RemoteEndPoint;
string ip = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
NetworkStream stream = tcpClient.GetStream();
byte[] receivedBytes = new byte[tcpClient.ReceiveBufferSize];
stream.Read(receivedBytes, 0, receivedBytes.Length);
f.UpdateData(receivedBytes, ip);
}
Sender Method to send data -
public void Sender(byte[] data, TcpClient client)
{
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
}
As you can see I have called Run() method in formLoad. But this all is not working as I dont have much knowledge of threads.
This method is not continuous. The server is not listening to clients always. Can someone help me with this. I need asynchronuous tcp listener that can listen to incoming clients and that too in windows form. Console Server I have.
I saw on the internet how to create a socket server in C#,
after sending to the server one message the server closes.
I have been wondering what can I do to change it so it can handle multiple messages.
The code:
static void startServer() {
Console.WriteLine("[*] Opening server...");
TcpListener listener = new TcpListener(IPAddress.Any, 45784);
listener.Start();
Console.WriteLine("[*] Server waiting on port " + 45784);
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("Client connected!");
StreamReader STR = new StreamReader(client.GetStream());
Console.WriteLine(STR.ReadLine());
}
static void Main(string[] args)
{
string ip = GetIpAdress();
Console.WriteLine("server on: " + ip);
startServer();
Console.Read();
}
I believe this is pretty basic. Simply put your code read only one message and exit.
To read multiple message you just need to put a while loop around this line.
Console.WriteLine(STR.ReadLine());
Your server is stopping after receiving one message because that's all you've told it to do (so far).
These lines:
StreamReader STR = new StreamReader(client.GetStream());
Console.WriteLine(STR.ReadLine());
Will handle one message from the client, and then stop since you aren't telling it to grab another message.
If you want the server to listen and handle an arbitrary number of messages, you'll want to put this code in a loop.
Try this:
static TcpListener StartServer()
{
Console.WriteLine("[*] Opening server...");
TcpListener listener = new TcpListener(IPAddress.Any, 45784);
listener.Start();
Console.WriteLine("[*] Server waiting on port " + 45784);
return listener;
}
static void Listen(CancellationToken cancellationToken)
{
string ip = GetIpAddress();
Console.WriteLine("server on: ");
var listener = StartServer();
var client = listener.AcceptTcpClient();
Console.WriteLine("Client connected!");
var reader = new StreamReader(client.GetStream());
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine(reader.ReadLine());
}
}
static void Main(string[] args)
{
var cancellationSource = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cancellationSource.Cancel();
};
Listen(cancellationSource.Token);
}
This code will continue to get lines from the remote client until the server is canceled with Ctrl-C. It uses a CancellationToken to hook into the cancellation event, but you could also use a bool flag if you wanted.
Caveats: This only accepts messages from a single client, not multiple clients (that's a different challenge). Also, once the cancel event is sent, the server waits for one more message from the client before exiting and closing the connection, because ReadLine() blocks the thread until it sees a message come in.
I meant, multiple messages, one after the other from a single client.
You need to add some loops.
listener.Start();
while(true) { // beware: please avoid never-ending loop, and define a proper exit condition
TcpClient client = listener.AcceptTcpClient();
using(client) {
Console.WriteLine("Client connected!");
StreamReader STR = new StreamReader(client.GetStream());
string s = STR.ReadLine();
while(s != null) { // read until EOF
Console.WriteLine(s);
}
}
}
listener.Stop(); // this should always be called after exit condition occurs
I have a simple TCP/IP program to read data from a machine and write it into text file. I want to run it as Windows Service so that data gets written into text file continuously with out any intervention. Now when I try to run the program under debug mode of Visual Studio, it is reading the data from the machine and saving into text file, but as soon as I add it as Windows Service and try to start the service, it is giving following error message..
windows service could not start the service on the local computer
error:1053 The service did not respond to the start or the control request in a timely fashion
Here is my main applications code..
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
Here is my code to communicate to the machine using TCP/IP and read/write data into text file..
protected override void OnStart(string[] args)
{
ipaddress = "";
int port = int.Parse("");
textfileSaveLocation = "";
byte[] data = new byte[1024];
string stringData;
IPAddress ipadd = IPAddress.Parse(ipaddress);
IPEndPoint ipend = new IPEndPoint(ipadd, port);
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.NoDelay = false;
try
{
sock.Connect(ipend);
}
catch (Exception dfg)
{
return;
}
try
{
buf = String.Format("SMDR", "PCCSMDR");
bBuf = Encoding.ASCII.GetBytes(buf);
sock.Send(bBuf);
while (true)
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
string df = "";
try
{
FileStream dr = new FileStream(textfileSaveLocation, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
StreamReader fg = new StreamReader(dr);
df = fg.ReadToEnd();
fg.Dispose();
dr.Dispose();
}
catch (Exception dfjdfs)
{
}
try
{
FileStream cd = new FileStream(textfileSaveLocation, FileMode.Create);
StreamWriter cdf = new StreamWriter(cd);
cdf.WriteLine(df);
cdf.WriteLine(stringData);
cdf.Dispose();
cd.Dispose();
}
catch (Exception hgy)
{
}
}
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
catch (Exception DFGFD)
{
}
}
My only aim with this program is to run it as Windows Service through installer and start the service. Once the service is started, it should read the data from the given ip and port of the machine and save it into text file. Also I need this service to continuously monitor for the data from the machine and once new data comes to the machine, it should read and write into the text file.
Do I need to implement Multi-threading in the program?
The system expects the OnStart method to return in a timely fashion (~30 seconds), so long-running tasks like monitoring for data need to be moved to another thread. This can be as simple as:
private System.Threading.Thread _thread;
protected override void OnStart(string[] args)
{
_thread = new Thread(DoWork);
_thread.Start();
}
private void DoWork()
{
// create and monitor socket here...
}
Note that while your while (true) loop is sufficient to keep the thread running, it makes it difficult to stop it when the service stops. For this, I use a ManualResetEvent like so.
using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private void DoWork()
{
// initialize socket and file
// thread loop
while (!_shutdownEvent.Wait(0))
{
// read socket, write to file
}
// close socket and file
}
protected override void OnStop()
{
_shutdownEvent.Set();
_thread.Join(); // wait for thread to stop
}
I agree with Matt's answer.
Also, In general , it is good to add an option to debug your service, here is an example:
protected override void OnStart(string[] args)
{
bool launchDebugger = false;
if (args.Count() > 0)
{
launchDebugger = args[0].ToLower() == "debug";
}
if (launchDebugger)
{
Debugger.Launch();
}
}
When you run the service with an argument: "debug", it will trigger a fake exception,
allowing you to debug the service with visual studio.
I have the following code which I want to implement as my server. As I understand it is async. and should allow connections from multiple clients...
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
while (true)
{
IAsyncResult res = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
connectionWaitHandle.WaitOne();
}
}
private void HandleAsyncConnection(IAsyncResult res)
{
TcpListener listener = (TcpListener)res.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(res);
connectionWaitHandle.Set();
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}
I have a test app which simply fires requests to my server. As you can see in the code the server just replies with its date/time. The test app sends say 20 requests which are simply test strings. For each of these requests it opens a socket, sends the data to my server and then closes the socket again.
This works fine with one test app running. However, if I open two test apps the second one cannot connect to the server. I thought because I am handling the request async. and because my test app opens then closes the socket before each call I could handle requests from multiple clients?
Edit
If using >=.Net4.5, it's better to use the new network methods that then permit the adoption of async and await. As such, it might be better to follow the example I provided in this post as a starting point.
Original Post
The following code demonstrates how to accept multiple clients asynchronously without spinning off a new thread per connection.
private TcpListener listener;
public void Start()
{
listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
StartAccept();
}
private void StartAccept()
{
listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
}
private void HandleAsyncConnection(IAsyncResult res)
{
StartAccept(); //listen for new connections again
TcpClient client = listener.EndAcceptTcpClient(res);
//proceed
}
You can use this pattern for most async operations.
The way you did it, there is no benefit compared to using AcceptTcpClient. Simply loop and create a new thread for each accepted connection:
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
while (canRun)
{
var client = listener.AcceptTcpClient();
new Thread(ClientThread).Start(client);
}
}
private void ClientThread(IAsyncResult res)
{
TcpClient client = (TcpClient)res.AsyncState;
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}
A golden rule when using asynchronous methods is to NOT block the operation. Blocking would defeat the purpose of using async ops.
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
listener.BeginAcceptTcpClient(OnAccept, listener);
}
private void OnAccept(IAsyncResult res)
{
TcpListener listener = (TcpListener)res.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(res);
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}