Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Socket based TCPServer as window service problem

Status
Not open for further replies.

nastoski

Technical User
Oct 21, 2003
21
Hi all,
I'm trying to make a simple TCP server (windows service) that listens a particular port and receive simple request.

My TCP server is:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Configuration;

namespace Codelab.TcpServerService
{
public class TcpServerService : System.ServiceProcess.ServiceBase
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

private readonly int port = 48888;
private IPAddress ip;
private TcpListener listener;
private bool isStopped = false;

public static TraceSwitch traceSwitch = new TraceSwitch("traceSwitch", "Trace Switch");


public TcpServerService()
{
Trace.WriteLineIf(traceSwitch.TraceInfo, String.Format("{0}: TcpServerService()", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
// This call is required by the Windows.Forms Component Designer.
InitializeComponent();

// TODO: Add any initialization after the InitComponent call
}

// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;

// More than one user Service may run within the same process. To add
// another service to this process, change the following line to
// create a second service object. For example,
//
// ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
//
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new TcpServerService() };

System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.CanShutdown = true;
this.ServiceName = "TCP Server Service";
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
Trace.WriteLineIf(traceSwitch.TraceInfo, String.Format("{0}: OnStart()", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
this.ip = IPAddress.Parse(ConfigurationSettings.AppSettings["IP"]);
this.listener = new TcpListener(ip, port);
// TODO: Add code here to start your service.
this.isStopped = false;
Thread t = new Thread(new ThreadStart(this.Start));
t.Start();
}

/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
this.isStopped = true;
}

public void Start()
{
Trace.WriteLineIf(traceSwitch.TraceInfo, String.Format("{0}: Start()", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
this.listener.Start();

Socket s;
Byte[] incomingBuffer;
Byte[] time;
int bytesRead;

while (!this.isStopped)
{
Trace.WriteLineIf(traceSwitch.TraceInfo, String.Format("{0}: Loop()", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
s = this.listener.AcceptSocket();
incomingBuffer = new Byte[65535];
bytesRead = s.Receive(incomingBuffer);

time = Encoding.ASCII.GetBytes(
System.DateTime.Now.ToString().ToCharArray());
s.Send(time);
}

this.listener.Stop();
Trace.WriteLineIf(traceSwitch.TraceInfo, String.Format("{0}: Stop()", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
}
}
}

Upon every request the server listen the port 48888 and return current system time.

On the other hand tcp client is:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Codelab.TcpClient
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class TcpClient
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
byte[] data = new byte[1024];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.1.3"), 48888);

Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);

try
{
server.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
return;
}

int recv;
bool finished = true;
while(finished)
{
input = Console.ReadLine();
if (input == "exit")
finished = true;
server.Send(Encoding.ASCII.GetBytes(input));
data = new byte[65535];
recv = server.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
}
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();

}
}
}


However when I run the client application I receive a result (datetime converted string) only for first request to TCP server, but when I tried to send data to server once again my client program is stacked on
recv = server.Receive(data). If I run several client applications at once the same thing happens, each client receives data only for first request, but not for following once.

Does someone can help me?

Regards

Igor

 
From what I can tell, you have a sockets variable (s), and then a WHILE {} loop that goes infinately until you stop your service..

Now here is where I see the problem...

each time the WHILE loop completes, it destroys the sockets variable and creates a new one.. whether there is a connection or not.. the first time your client connects, the while loops catches it, sends data, and starts the loop again, killing the reference to the currently connects Socket variable (s) and starting a new one.. any further attempts to send information from the client, goes into a void, since this connection is technically closed. In C#, once you no longer reference an object, it is cleared from memory (thereby closing your TCP connection).

What you really need to do is create an event handler that will trigger a sequence of multiple connections without terminating the current connection.. In breif, here is a quick and dirty outline of what needs to happen:

1- Start listener thread...

2- Listener thread sits in an infinate loop until asked to stop

3- Connection event fires and the handler starts another thread to handle this connection. Your main listner thread then continues to wait for other connections.

4- Your new connection thread assigns a new Sockets object - Because it is a different thread, it will not distroy previous socket objects created in other threads.

5- Handle your connection until it is closed by the client, then release/kill the thread handling that connection. This way, you can send multiple requests to your TCP server from multiple connections without any problems.

I hope this helps....

Cheers,

G.

Oxigen - Next generation business solutions
-----------------------------
Components/Tools/Forums/Software/Web Services
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top