views:

194

answers:

3

I have a simple server that waits for a client to connect, reads the incoming stream, and sends a message back. What I would like to do is have every connection handled by a separate thread. This is my first time working with sockets and threads in C#, and most of the examples I have found are really confusing, so any help or simple examples would be much appreciated.

Here is what I have right now.

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;

    [STAThread]
    static void Main(string[] args)
    {
     TestServer ts = new TestServer();
         ts.Start();
    }

class TestServer
{
    private readonly int port = 48888;
    private readonly IPAddress ip = IPAddress.Parse("127.0.0.1");

    private TcpListener listener;

    public TestServer()
    {
       this.listener = new TcpListener(this.ip, this.port);
    }

    public void Start()
    {
     this.listener.Start();
     Console.WriteLine("Server Running...");

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

     while (true)
     {
      s = this.listener.AcceptSocket();

      incomingBuffer = new Byte[100];
      bytesRead = s.Receive(incomingBuffer);
      string message = "Hello from the server";
      Message = Encoding.ASCII.GetBytes(message.ToCharArray());

      s.Send(Message);
     }
    }
}
A: 

Try this:

public void Start()
{
    this.listener.Start();
    Console.WriteLine("Server running...");

    while (true)
    {
        Socket s = this.listener.AcceptSocket();
        ThreadPool.QueueUserWorkItem(this.WorkMethod, s);
    }
}

private void WorkMethod(object state)
{
    using (Socket s = (Socket)state)
    {
        byte[] buffer = new byte[100];
        int count = s.Receive(buffer);
        string message = "Hello from the server";
        byte[] response = Encoding.ASCII.GetBytes(message);
        s.Send(response);
    }
}
Matthew Ferreira
A: 

Use a threadpool. You can use instantiate threads manually but since you have might have a huge number of connections, a threadpoool is more efficient.

System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(processMessage), socket);

processMessage is the method that will process the message. And there will be one thread per connection. Really simple actually.

Bobby Alexander
What is the difference between ThreadPool.QueeuUserWorkItem(this.processMessage, socket) and ThreadPool.QueueUserWorkItem(new WaitCallBack(processMessage), socket) ?
Tester101
@Tester101: The first parameter has to be a delegate of type WaitCallback. You cannot directly pass a method there. So I wrapped the method in the delegate and passed it. You cannot pass processMessage directly as the first argument.
Bobby Alexander
A: 

Not answering your question directly, but ...

Thread pools are not about 'new thread per connection', they are about having some meaningful number of threads (with some relation to number of cores on the box) already running and waiting for work. This "work" is given to the pool by the producer thread (the one accepting the connections in your case) via one or more queues.

Please note that this is not always the best solution though. Take a look at C10K and at Hight Performance Server Architecture pages.

Nikolai N Fetissov