C# Tutorial - Simple Threaded TCP Server

Skill

C# Tutorial - Simple Threaded TCP Server

Posted in:

In this tutorial I'm going to show you how to build a threaded tcp server with C#. If you've ever worked with Window's sockets, you know how difficult this can sometimes be. However, thanks to the .NET framework, making one is a lot easier than it used to be.

What we'll be building today is a very simple server that accepts client connections and can send and receive data. The server spawns a thread for each client and can, in theory, accept as many connections as you want (although in practice this is limited because you can only spawn so many threads before Windows will get upset).

Let's just jump into some code. Below is the basic setup for our TCP server class.

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

namespace TCPServerTutorial
{
  class Server
  {
    private TcpListener tcpListener;
    private Thread listenThread;

    public Server()
    {
      this.tcpListener = new TcpListener(IPAddress.Any, 3000);
      this.listenThread = new Thread(new ThreadStart(ListenForClients));
      this.listenThread.Start();
    }
  }
}

So here's a basic server class - without the guts. We've got a TcpListener which does a good job of wrapping up the underlying socket communication, and a Thread which will be listening for client connections. You might have noticed the function ListenForClients that is used for our ThreadStart delegate. Let's see what that looks like.

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);
  }
}

This function is pretty simple. First it starts our TcpListener and then sits in a loop accepting connections. The call to AcceptTcpClient will block until a client has connected, at which point we fire off a thread to handle communication with our new client. I used a ParameterizedThreadStart delegate so I could pass the TcpClient object returned by the AcceptTcpClient call to our new thread.

The function I used for the ParameterizedThreadStart is called HandleClientComm. This function is responsible for reading data from the client. Let's have a look at it.

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();
}

The first thing we need to do is cast client as a TcpClient object since the ParameterizedThreadStart delegate can only accept object types. Next, we get the NetworkStream from the TcpClient, which we'll be using to do our reading. After that we simply sit in a while true loop reading information from the client. The Read call will block indefinitely until a message from the client has been received. If you read zero bytes from the client, you know the client has disconnected. Otherwise, a message has been successfully received from the server. In my example code, I simply convert the byte array to a string and push it to the debug console. You will, of course, do something more interesting with the data - I hope. If the socket has an error or the client disconnects, you should call Close on the TcpClient object to free up any resources it was using.

Believe it or not, that's pretty much all you need to do to create a threaded server that accepts connections and reads data from clients. However, a server isn't very useful if it can't send data back, so let's look at how to send data to one of our connected clients.

NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

Do you remember the TcpClient object that was returned from the call AcceptTcpClient? Well, that's the object we'll be using to send data back to that client. That being said, you'll probably want to keep those objects around somewhere in your server. I usually keep a collection of TcpClient objects that I can use later. Sending data to connected clients is very simple. All you have to do is call Write on the the client's NetworkStream object and pass it the byte array you'd like to send.

Your TCP server is now finished. The hard part is defining a good protocol to use for sending information between the client and server. Application level protocols are generally unique for application, so I'm not going to go into any details - you'll just have to invent you're own.

But what use is a server without a client to connect to it? This tutorial is mainly about the server, but here's a quick piece of code that shows you how to set up a basic TCP connection and send it a piece of data.

TcpClient client = new TcpClient();

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

client.Connect(serverEndPoint);

NetworkStream clientStream = client.GetStream();

ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

The first thing we need to do is get the client connected to the server. We use the TcpClient.Connect method to do this. It needs the IPEndPoint of our server to make the connection - in this case I connect it to localhost on port 3000. I then simply send the server the string "Hello Server!".

One very important thing to remember is that one write from the client or server does not always equal one read on the receiving end. For instance, your client could send 10 bytes to the server, but the server may not get all 10 bytes the first time it reads. Using TCP, you're pretty much guaranteed to eventually get all 10 bytes, but it might take more than one read. You should keep that in mind when designing your protocol.

That's it! Now get out there and clog the tubes with your fancy new C# TCP servers. As always, comments and questions are welcome.

Want to learn more about TCP programming in C#? Check out these great books:

Viswanathct
11/02/2007 - 13:04

I searched a lot for a simple article in tcp reading / writting.

After googling with several alternatives i found this page.

Simply Good & simple.

- Thx.

reply

Anonymous
07/13/2009 - 12:50

Check MSDN they have a great example.

reply

bst78
07/16/2010 - 08:47

Please show me the microsoft's example. This example is very very good!

If you mean the example with server and "dummy" remote server object (http://support.microsoft.com/kb/307445) I can not agree with you :-)

reply

Anonymous
02/22/2011 - 04:09

Very thnx. Excellent. I learned tcp from here...

reply

Mas-Tool
11/07/2007 - 08:52

Yep, it's very simple if you're writing a console application.
Try making a chat with with .NET sockets and you'll figure out there are no events support :-/
unlike VB6 with Winsock :)

reply

The Reddest
11/07/2007 - 09:15

Can you elaborate on the events support? A few years ago a couple of us built a simple chat application using the framework above without any issues.

reply

Mas-Tool
11/08/2007 - 02:17

Hi again :)
Well, if you need to make a chat like application you have to use a non-blocking sockets right ? so you use async methods (BeginReceive/EndReceive BeginConnect/EndConnect etc) but the problem is the once you received some data or got connected, you're AsyncCallback is fired and you're on a seperate thread ! so you have to Invoke the mothods for the GUI's thread to know you've received some data :-/
But how can you invoke a method if you're a "pure" class and not a control with a parent control to call the Invoke method?

That's the way i see it, but maybe I'm wrong :)
I'de like to know what you think!

Mas-Tool

reply

The Reddest
11/08/2007 - 09:24

I don't really like using the Async callbacks so I opted for a blocking socket sitting on its own thread. When a message was received, I would then fire an event out of the "pure" class that can be caught by a higher level control. My event handler would contain the message that was received. The control would then invoke a method to display the message to the GUI.

That's the architecture I like to follow, but of course it won't work for every application.

reply

cyclotis04
06/01/2010 - 15:19

I'm designing a similar class, but I would like to keep from checking InvokeRequired every time an event is raised. I've finally ended up creating a Synchronization Context object when my form calls the object, and passing that context around, on which I raise events. It makes sense to me that events should be raise on the thread their calling object's begun on. For example, "DataReceived" will be raised on whichever thread calls "ListenForData". What are your thoughts on this method?

reply

bigginer
02/22/2010 - 11:20

hi
mybe it`s so funy but where is the main method to start
compiling for this program and , where is the place of
final code(code before client code)in this program.

reply

Anonymous
07/06/2011 - 02:45

You should try to NOT just copy and paste the code.

Make sure you understand it first!

reply

Martijn Dwars
12/01/2007 - 08:08

A little parse error in your client program:

IPEndPoint serverEndPoint =
   new IPEndPoint(IPAddress.Parse("127.0.0.1", 3000);

Needs to be:

IPEndPoint serverEndPoint =
   new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

reply

The Reddest
12/01/2007 - 09:23

Good catch. I've corrected the post.

reply

suresh kallem
02/28/2012 - 00:56

Im new to TCPIP programming, please help me sort out the following problem,

i have once server and many clients(around 500 numbers). client system connected to the many hardware devices. server have to monitor client systems status, connected devices and its status and many other operations.
here client should send their status to server for every interval of time and server should display it.

please suggest me on the same.

reply

David
01/15/2008 - 07:20

Very good tutorial. clear and simple.
thanks a lot

reply

AnilKumarVerma
02/06/2008 - 05:42

I am searching for windows version of it,it is too simple for beginers

reply

Some
02/09/2008 - 05:08

Anybody know how to connect via internet?
PC1->routerA->internet->routerB->PC2

reply

Anonymous
12/27/2010 - 05:02

In this case i expect that you have to make sure that your routers are properly configured. Depending on the type of your router you may have to use the "Port forwarding" of protocol TCP @ your port used by your application.

e.g. application uses port 3000 then routerA will need to forward incoming TCP connection on port 3000 to your PC1. Secondary routerB will need to be configured to forward incoming TCP connections on port 3000 to PC2.

additionally any firewall has also to be "pinned" @ port 3000 so that your application can talk through the whole "IP-devices-chain"

i tried this a few months ago with an cellphone via IP-network to an Windows PC behind NAT and it worked fine about nearly that way.
(PC->router->internet->cell-network->cellphone GPRS channel)

reply

Manish
02/11/2008 - 14:31

is there a simple version of this for .net 1.1? specifically with regards to closing the connection releasing client resources to be able to use them again, the next time a connection comes in...

reply

Tony
02/19/2008 - 19:03

Is there a particular reason for starting a thread in the constructor? As far as I can tell there would be no difference just calling ListenForClients() and it creates its own threads.

reply

The Reddest
02/19/2008 - 20:09

ListenForClients is going to block whatever thread calls it while it listens for client connections. Most of the time, my Server class is created on the main thread. I don't usually want to block my main thread while waiting for connections, so I created another thread which can be blocked without affecting the rest of my application.

reply

Working Class Hero
02/21/2008 - 07:08

When I close my win forms serverapplication (in debug state) it does not kill that thread. So what should I do? How I kill that clientThread and listenThread?

reply

The Reddest
02/22/2008 - 10:55

For the clients, you'll want to call Close on their NetworkStreams. This will cause the read to unblock and throw an exception which will be caught by the exception handler (which breaks out of the loop, ending the thread).

On the TcpListener, you'll have to call Stop. I'm not sure exactly what this will do to the blocking AcceptTcpClient call. It will either unblock and return null, or it will throw an exception. Either way, you'll want to stick in some error handling. When the error is caught, simply break out of the listen loop.

reply

Working Class Hero
02/25/2008 - 00:26

YES! it worked! yippee
thanks a lot!

reply

Pc_Madness
02/26/2008 - 06:11

Sorry to be the newb.. but does someone have/know of an example of how to get data to and from the class to a form? :(

*sigh* I had an awesome idea for a program, but can't actually make a start on it cos I have to get this TCP stuff out of the way and I have no idea whats going on. :( I miss Winsock.. now that was simple. :)

reply

The Reddest
02/26/2008 - 08:25

If by "the class" you mean the TCP server class, then it's not too hard. Inside the HandleClientComm thread, fire an event with the data that can be caught by your Form.

public delegate void MessageReceivedHandler(string message);
public event MessageReceivedHandler MessageReceived;

...

//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
string message = encoder.GetString(message, 0, bytesRead);
if(this.MessageReceived != null)
  this.MessageReceived(message);

Depending on how much information you need, you might want to also pass the TcpClient through your event as well. For a tutorial on custom event handlers, check out this post.

Now all you have to do is hook the event from your form.

Server server = new Server();
server.MessageReceived += new MessageReceivedHandler(
  Message_Received);

void Message_Received(string message)
{
  //update the display using invoke
}

Since the events are fired on the server thread, you can't update the form directly - because you can't modify UI elements on threads that didn't create them. You'll have to use Invoke, which executes code on the UI element's thread. For some more information on invoking, I would recommend this article.

I hope this helps.

reply

Pc_Madness
02/27/2008 - 17:01

woot, thanks Reddest. :)

reply

Anonymous
02/22/2011 - 04:26

thnx Sir. I like it

reply

Yakir Manor
12/18/2011 - 12:00

the way i connected winform is as following:
the server has 1 form and the project contain server class, the form has rich text box and two buttons: start and stop:
Main.cs (Form)

 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net.Sockets;
using System.Threading;
using System.Net;


namespace PhyTechTcpServer
{
    //
    public delegate void MessageReceivedHandler(string message);
    public partial class Main : Form
    {
        private static Mutex mut = new Mutex();
        Server server;
        int msg_counter = 0;
        public Main()
        {
            InitializeComponent();
            btn_ServerStop.Enabled = false;          
            rtb_Input.ReadOnly = true;
        }

        private void btn_ServerStart_Click(object sender, EventArgs e)
        {
            btn_ServerStop.Enabled = true;
            btn_ServerStart.Enabled = false;
            server = new Server(rtb_Input);
            server.MessageReceived += new MessageReceivedHandler(Message_Received);
            server.server_start();                        
        }

        private void btn_ServerStop_Click(object sender, EventArgs e)
        {
            btn_ServerStop.Enabled = false;
            btn_ServerStart.Enabled = true;
            server.server_stop();
        }
        void Message_Received(string message)
        {
            //update the display using invoke
            Invoke(new MessageReceivedHandler(PrintToScreen), new object[] { message });
        }
        private void PrintToScreen(string msg)
        {
            msg_counter++;
           
            rtb_Input.AppendText("msg no': " + msg_counter + System.Environment.NewLine + msg + System.Environment.NewLine);
        }
    }
}

the Server.cs class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace PhyTechTcpServer
{    
    class Server
    {        
        private RichTextBox _rtb_Input;
        private TcpListener tcpListener;
        private Thread listenThread;

        public Server(RichTextBox rtb_Input)
        {
            _rtb_Input = rtb_Input;
        }
        public void server_start()
        {
            this.tcpListener = new TcpListener(IPAddress.Any, 8080);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));

            _rtb_Input.AppendText("Listening... Press any key to stop" + System.Environment.NewLine);
            this.listenThread.Start();
        }
        public void server_stop()
        {
            _rtb_Input.AppendText("Listener aborted" + System.Environment.NewLine);

            this.listenThread.Abort();
            this.tcpListener.Stop();
        }

        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);
            }
        }
       
        public event MessageReceivedHandler MessageReceived;
        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();
                string msg = encoder.GetString(message, 0, bytesRead);
                if (this.MessageReceived != null)
                {
                    this.MessageReceived(msg);
                }
                //send message back select the message from the db
                byte[] buffer = encoder.GetBytes("Hello Client!");

                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();
            }
            tcpClient.Close();
        }
    }
}

the client has 1 form with 1 rich text box and 1 button: send data, all the client code is in the form,
the form code:

 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace PhyTechTcpClient
{
    public partial class PhyTechTcpClient : Form
    {
        public PhyTechTcpClient()
        {
            InitializeComponent();
            rtb_Outpot.Text = "# firmware ver: 1.25.6996" + System.Environment.NewLine + "# current time: "+ DateTime.Now.ToString() + System.Environment.NewLine + "# simple csv file:" + System.Environment.NewLine + "TimeStamp;Value" + System.Environment.NewLine + "12:30 01.01.11;0.06" + System.Environment.NewLine + "16:45 01.01.11;0.08";
        }
        private void btn_ClientStart_Click(object sender, EventArgs e)
        {
            TcpClient client = new TcpClient();

            IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
            try
            {
                client.Connect(serverEndPoint);
                NetworkStream clientStream = client.GetStream();

                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] buffer = encoder.GetBytes(rtb_Outpot.Text);

                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();
            }
            catch (Exception ex)
            {
                rtb_Outpot.AppendText(System.Environment.NewLine + "Failed To Connect to the Server" + System.Environment.NewLine);
            }  
        }
    }
}

reply

Jaelius
02/07/2012 - 18:47

Awesome, easy to understand, easy to use..
Thanks a lot for this job !

reply

Chris Surfleet
02/27/2008 - 08:49

OK, I think I must be missing something here. I keep getting an error stating "You must call the start method before calling this method" on the TcpClient client = this.tcpListener.AcceptTcpClient() line.

I've definately started the server, any ideas what this could be?

Thanks a lot!

reply

The Reddest
02/27/2008 - 11:37

That error is a result of not calling tcpListener.Start() before the call to AcceptTcpClient(). If you're saying you definitely called it, then I don't have any other ideas. I'd double to check to make sure you absolutely called tcpListener.Start().

reply

Chris Surfleet
02/28/2008 - 03:41

Hmm got a little further. The problem is to do with closing the server down. I can send data to it without error the first time, (creating the server object and sending the data from the same test case method) but next time I run the code I get a "Only one usage of each socket address (protocol/network address/port) is normally permitted" exception. I added a method to my server called Close that simply calls Abort on the listen thread and Stop on the TcpListener. If I call this after closing my request stream I get an IO exception while writing to the stream, above the point where I call the close method??

Really confused haha

reply

The Reddest
02/28/2008 - 12:04

Calling Abort is never a good way to close your threads - and it's not actually a guarantee that the thread will terminate. Calling Stop() on your TCPListener should unblock your listen thread and throw an exception - which you should catch and return out of your function (which will end the thread).

Your first error is caused by calling Start() while another application is listening on that port. Typically, you can't have two TCP servers listening on the same port. Either your TcpListener was still running when you launched the application again, or you have another piece of software on your computer using that port.

reply

Dinesh
08/04/2011 - 23:26

I stopped the tcplistener ,still i am getting the above error .

reply

IdleByte
09/09/2011 - 13:11

I got past this error by using a dummy tcpclient to connect and close as part of the shutdown threads steps.
"
TcpClient testclient = new TcpClient();
testclient.Connect(IPAddress.Loopback, 9996); //9996 = change to port your listener is 'stuck' on
testclient.Close();
"
This will help 'emulate' something connecting to the port as far as the tcplistener is concerned. I also set a appclosing bool that i use to prevent threads from starting or erroring after the listener recovers.

reply

IdleByte
09/09/2011 - 13:43

Sorry, this was meant for someone else, wrong page :)

reply

JS
03/17/2008 - 05:14

Excellent tutorial! Thanks a lot!

reply

Vishav Bandhu Sood
04/03/2008 - 04:09

when i got connected to the various clients in tcp listner(server)suppose initially if there are 1000 clients connected
but after some time it shows only 500 or 400 clients connected.actually clients are connected but server is not responding prooerly,but after stopping server it agains shows the actual no of the clients connected.(i thinks this problem is related to server port buffer size)plz help .....

reply

Simnesh
04/08/2008 - 16:24

Hi,

i want to send data from a client to another client through server...

please help me

reply

The Reddest
04/09/2008 - 10:40

How to do this depends a lot on the application you're trying to make, your protocol, and your server architecture. Here's an example scenario that might get you started.

When a new client is connected, you could assign them a unique id, or they could actually send you the id (a username or email address). This id would then be sent from another client in a request to forward the information.

This would mean your protocol would have to include the id of the client the other client wants to send data to. On the server, you'd simply read the message, get the id of the client to forward the message to, iterate through your clients to find the recipient, then send the data.

reply

Simnesh
04/09/2008 - 21:21

Hi
Is it possible to send a class object from a TcpClient to TcpListener...
I want to send an object of a class or an array of string to the TcpListener

reply

The Reddest
04/10/2008 - 09:38

It sounds like remoting is what you might want here, but it can also be done using TCPClient and TCPServer.

The send an object, you'll first need to serialize it to a byte array. Then, on the receiving end, deserialize the object back into the desired object. Here's a tutorial I found on the web explaining how to do this: Object Serialization and Deserialization in C#.

reply

Simnesh
04/18/2008 - 05:57

Thanks alot Reddest...

i have one more question...
This TCPServer should run as a standalone application..or It can be programmed for a web service...

because I just want to run TCPServer as web servce in the server...

Please Help Me

reply

Nigel Bogle
05/03/2008 - 06:24

I have an application which is essentially a TCP/IP Server to which up to 16 clients can connect at any one time each on it's own unique port, i.e. 4001 - 4016.

The connections establish ok but after a period of time the connections seem to disconnect and I'm not sure why. when you run NETSTAT from the DOS Prompt it shows the connections in a CLOSE_WAIT state.

The clients then have to reconnect... and so the loop goes on...

Whe I try to write back to the client and it is disconnected I get an error code of 10053 which means that the software in the host machine has disconnected or something along those lines.

Has anyone else had experience of this? Could it be a timeout? How can I ensure that once my server accepts a client connection that it helps to maintain the established connection?

Any and all help appreciated.

Nigel.

reply

Dvaz
06/02/2008 - 13:05

Thanks for the nice tutorial, just found it today.

Is there a way to start the server in its our thread at start? The reason i ask is because the user on my UI needs to click a button to start listening, but by doing so, it blocks my main UI.

Thanks!

reply

The Reddest
06/02/2008 - 13:25

The server in this tutorial is created in its own thread. The constructor of the Server class creates the thread and begins the listening process. All you'd have to do is not call this.listenThread.Start() until the user clicks the button.

reply

Dvaz
06/03/2008 - 13:07

Ahh, i see. I used a background worker to call the listen call and it also worked, will try the other.

One more thing, i am trying to pass a connected / disconnected status to the mainform as wel as the number for files received, any easy way to do that? So far im using you event example to send the message back but what are the procedures if i want to send more data back to my MainForm?

-Thanks!

reply

Tagnard
06/09/2008 - 07:17

Hi. i am trying to get the client to read what the server sends but i am new to this. Can you tell me what i am doing wrong?

http://tagnard.net/2008/06/09/c-serverclient/

reply

Eric
06/13/2008 - 04:46

Thanks for the nice tutorial. I tried it (ported to C++) and it works fine. Still, when exiting the main application I can't find a way to stop a clientThread when there is an active connection. I mean I can use tcpListener.Stop(), what causes a SocketException that unblocks AcceptTcpClient()in the ListenForClients thread, then I use break to exit the loop and this thread.
But if a client is actually connected, corresponding HandleClientComm thread remains stuck waiting for something to be read. So far, I haven't found any clean way to gracefully close the socket and to exit this thread.

I don't see how to close the NetworkStreams (as proposed in an earlier comment.) from the outside of the client thread. And from the inside, well the read is blocking, so...

Any idea?... Thanks, Eric

reply

The Reddest
06/13/2008 - 07:17

I usually create an object for clients. The thread would be located inside the client object. The server would just keep a list of clients and whenever you stop the server, you'd loop through each client and call a stop function on them, which calls Close on their NetworkStreams.

You can modify the above code to do something similar by keeping a List of just the NetworkStreams. Whenever a new client is connected, add the NetworkStream from HandleClientComm. Whenever a client is disconnected, remove the NetworkStream from the list.

reply

Eric
06/23/2008 - 05:00

thanks for the suggestion, it made it.

reply

Johan
06/14/2008 - 18:48

Hi, have a strange problem... the tcp server connects fine with clients on the local network but 'kind of' connect with client comming from the Internet... it always wait about 16 - 20 seconds to connect, but then the remote client seems not to realize this... (also tcp port monitors show the incomming connection connecting almost immediately, but somehow not telling the server) please help...

reply

Nicholas
06/17/2008 - 21:10

Hi, i have an error message
"A blocking operation was interrupted by a call to WSACancelBlockingCall" when set tcplistner.stop(), how to solve it ?

thank you

reply

Eric
06/23/2008 - 05:00

this is normal behavior when interrupting a blocking socket (i.e. waiting for clients). WSACancelBlockingCall is called and a SocketException is thrown (see my post above). Just catch this exception and use it to exit the thread ('break' in the infinite while loop).

reply

Vitalij
06/19/2008 - 05:35

Hi!
If it's possible, send me an initial code of this program. Please!

reply

Jason
06/27/2008 - 08:10

Nice.. Easy to use and build on..

reply

Saga
07/02/2008 - 18:07

Hi,
Since i m very beginner in C# coding for TCP/IP server.. I can get the concept and working of the code through ur explanation and questions but i cant do it practically./. Can u please explain that with a visual mode or the screen shots of wat to do?

Please help me bro..
I m in need of it..
I will b very grateful for the help ...

reply

Saga
07/02/2008 - 18:09

ya its me again Saga..
Can u please mail me the one wich i asked in the previous thread...
My mail id: jeevan_saga@yahoo.co.in

reply

Opariti
07/04/2008 - 08:01

This is a great article; who explains clearly is really someone who really knows! I didn't give it a try yet but from the beginning it points to the TCPListener application blocking issue. I'll bring it into a chat-type application (client-server however) between two programs running on the same machine or remotely (first both on 'localhost'). I understand that threading the server separates it from the main program thread and avoid blocking all while in the listen loop. After acknowledging all that, just a stupid question (sorry I'm new to programming...): would it be possible that I make ListenForClients a method (rather than a class) of my main thread (since I want to quickly send and read messages from/into the main thread through your TCP server)? Many thanks!

reply

Bryan
07/08/2008 - 13:17

Hey, not much to add. Just wanted to say great thread. EXCATLY what i've been looking for.

THANKS!!!

reply

Serhat
07/09/2008 - 08:57

Thanks

reply

Shinoj K
07/14/2008 - 15:38

Hi,

i am in a big trouble to fix this problem....
can any one suggest me a control,
which can display animated gif images and text....

this is for a chat application....

reply

Kristian
07/16/2008 - 13:46

Ok... so I got the client-server part done quite easily...

What I want to do now is to have two way async communication using this only connection. Is that possible or do I have to have two connections, one for reading and one for writing, on different ports? Any other way you can suggest?

reply

Joap
07/16/2008 - 18:39

I have a very weird problem here. When I copy and paste the client into visual C# studio 2008, it doest recognise the .Connect method of a TcpClient.

Please help me! Thanks.

reply

Shinoj K
07/18/2008 - 11:28

Hi,
I have develeped webcam view in my chat.In that only one client can view webcam at time.I want to do view more than one client at time(web cam sharing).I am using TcpListner and TcpClient.Can Anyone Help Plz.Urgent.Thanks In Advance.

reply

Sami
07/23/2008 - 04:55

thank you

reply

Jeff
07/29/2008 - 18:41

Gonna try yours. Too soon to tell, but no crashes so far (like mine).

One issue I have always had with the GPS via GPRS devices we track: they will un-gracefully disconnect when they switch cell towers, then reconnect. So eventually, there's lots of dead connections that are not recylced. I tried making a collection and saving each client object as it's created. The idea was to purge the clients, but I am not sure how:

TcpClient client = this.tcpListener.AcceptTcpClient();
clientArrayList.Add(client);

...so now I have the client objects in my collection. But I get errors when I try to delete them like this:

foreach (TcpClient c in clientArrayList)
{
  c.Client.Close();
}

So I guess I am still looking for a way to recycle these old connections. Suggestions appreciated.

reply

Ken
08/04/2008 - 14:04

I would like to say thanks. The main article is detailed and straight forward but the additional information in the comments has also been very helpful.

reply

Kemp
08/23/2008 - 00:24

very simple as well useful beginner like me,,,,,,,.

reply

Martin
09/02/2008 - 07:32

Anybody,

have you had any issues with a (C#) socket exiting into a CLOSE_WAIT therefore not allowing to use the same address/port.? I am closing the connection at both ends and still get the CLOSE_WAIT (not all the time).

I used extensively C/C++ berkley socket and I never got the problem.

Anybody?

reply

Anonymous
10/17/2009 - 15:15

a CLOSE_WAIT usually indicates a problem in the app (server), probably from not closing the socket. You need to catch when the client closes (or times out/drops off/whatever) and close on the server side. You should see TIME_WAIT (ok), but CLOSE_WAIT is usually not good sign.

reply

Anonymous
09/27/2008 - 04:48

Good article, hope you will keep up ,creating more of it, in the same simplify style, someday. :)

Thx!

reply

Guilherme
10/25/2008 - 16:07

Good article!!!
Procurei por um assim a temposs..
muito bom msm ... parabéns!!

reply

Ron
11/10/2008 - 16:27

Excellent tutorial and very useful from both clarification and simplification perspectives.

Just one thing: shouldn't clientStream.Close() be called prior to tcpClient.Close() in HandleClientComm? Otherwise, won't the network stream remain open (unless if that was by design/intention, although I don't see why, and how, one could recover the same stream for future use after closing the TcpClient)?

Thanks again and great work!

reply

Leslie
11/27/2008 - 03:02

Awesome tutorial. Thanks Reddest.

reply

Robert
12/10/2008 - 15:58

I am new in this tcp programing and just have question:

I have created the TCPServer.dll and tcpClient.exe, how to test thme?

reply

Robert
12/10/2008 - 15:58

Sorry give the confuse, and question is simple: How to start TCPServer?

reply

The Reddest
12/10/2008 - 17:09

In my example code the server is started automatically upon construction.

reply

Johnny
12/24/2008 - 10:28

Hi there Reddest,
I am developing a MUD (multi user domain) in C# and i wanted to ask a question:

What i need is an application just like this, but i want the ability to have events driven by commands texted into the MUD, i’m sure you may be familiar with old school MUDs, if not its a text based D + D type adventure game, supporting multiple users that can interact. There will be chatting of course, but mainly each user will have commands and need series of data stored (in class objects i’m certain)

ANYWAY, What i need is to know if this threading business will affect each user? Like if i’m player Johnny and johnny does this or that in the game, how will other players in the room be made aware? IS this the wrong type of server for my needs? Thanks!

reply

Christiaan
12/26/2008 - 09:06

Exactly what I was looking for ^^

reply

Jester
12/28/2008 - 12:42

Forgive me if this has already been answered, but I didn’t see it.

Is there a way to send the chat messages the server receives to all the connected clients?

reply

Razvan
12/30/2008 - 05:57

Great code…simple and stable;

If you want to test your tcp server with simulated clients, you can use ‘telnet’ to achieve this.

Open a command prompt window in XP or Vista.

Type the following command:

telnet host port

where host=local computer name, ip address(127.0.0.1 will always be your own computer) or domain name that identifies the computer on the internet.
port = port number the TCP server is supposed to listen to

If you have a successfull connection then a black screen with a blinking cursor should appear.
If you open more command windows and issue the same command you will simulate multiple clients connected to the server.
Closing that command windows should disconnect that client.

Cheers,

reply

Razvan
12/30/2008 - 06:07

Forgot to mention:

sending information to your server using telnet and beeing able to parse it is not possible unless your TCP server uses VT100 Application layer protocol, which an end programmer has to manually implement it.Though i strongly discourage to do that.

You can use telnet to test server shutdown, while clients are connected and beeing able to easily troubleshoot exceptions, manage server resources when clients connect/disconnect and even troubleshoot timeout disconnect methods if you clients are connected, but donn’t send anything over a period of time.This is very a server memory friendly approach since a real server needs to handle thousands of simultaneous connections at a given time.

reply

Anonymous
12/30/2008 - 23:29

I can get the server to send information to the client, but its a blocking call. How do you make the client listen for incoming data from the server and keep the GUI alive at the same time?

Thanks in advance.

reply

Emil Haukeland
01/19/2009 - 17:19

Your tutorial was a great way to get starting on networking in C#. You are very good at explaining this hows og whys :)

Thanks a bunch!

reply

Wildhorn
02/04/2009 - 04:47

Man I registed JUST to tell you how amazing this tutorial is and how good you are at explaining stuff. I browsed I dont know how many tutorial about this without understand shit, but with you it was so simple, easy and amazing...

/bow

You are my new god! :)

reply

Brad Modenfield
02/25/2009 - 07:03

Hi thanks for good tutorials.
I have a serious problem. I want to develope an "server" that can recieve streaming data from sensors (the number of could be variated), Then the data should be pushed after it has been "modified" a bit, into the database (SQL Server).

I dont know where to start, im aware that it may will need some kind of a server and it looks like that i also need threads and async communication.

But how can i recieve stream data directly with TCP?

reply

hariom
03/04/2009 - 01:38

hi thanks for gud concepts..
but iam confused at Async ..

reply

Michael
03/05/2009 - 15:17

Worked the first time I used it. Many thanks, you saved my bacon...

reply

mahmoud
04/02/2009 - 08:27

greate explanation

reply

mahmoud
04/02/2009 - 08:29

but i think we will find "out of memory Exception"
when alot of clients conected
as we creare aseparate thread for Each client
so these no of threads will lead to that exception

reply

littleman
05/05/2009 - 08:22

Hi thanks, for the great tutorial,

BUT the NetworkStream.Read() command seems to work only the first time. I copied your code exactly (!), compiled and started the server. When I connect via telnet 127.0.0.1 3000 (or any other client) I can just send the first time. The second time NetworkStream.Read throws following Exeption.Message: "The argument is out of range of valid values! Parameter: size ...

Do you have any suggestions?

Cheers, littleman

reply

littleman
05/05/2009 - 08:39

solved .... :)

reply

Anon999
08/16/2010 - 05:31

Yes, please do tell us the solution, I am experiencing the exact same thing...

reply

The Reddest
05/05/2009 - 08:58

What was the issue?

reply

Muhammad Arshad
05/09/2009 - 01:38

Hi, Every one i have a card reader secrutiy device of pegasus brand, which is connected on port 4001 , i want to read and wirite data on this device any one help me please, while i am using Visual studio 2008 C# code

reply

Ohad
05/12/2009 - 05:02

Hi Reddest, great tutorial and code!

I was wondering what a realistic number of concurrently connected clients (=~ threads in this case) would be in this implementation, on a standard modern PC using winXP SP3 and VS 2008 / .NET 3.5 SP1

I realize this may depend on many factors, but a rough estimate would be great - dozens of clients? hundreds? thousands?

Much appreciated,
Ohad

reply

Jon Hunter
06/10/2009 - 09:38

Great article. Well written and easy to understand. I wish all articles were like this one !

reply

Anonymous
06/15/2009 - 16:32

Great article. One question though. Since the AcceptConection is blocking on the thread, How can I gracefully end everything when the Server, in my case a form, closes?

reply

The Reddest
06/15/2009 - 16:38

When TCPListener.Stop() is called, it will unblock with an exception. Simply catch the exception and break out of the loop.

reply

Anonymous
06/16/2009 - 11:27

that is what I was doing, just wanted to see if there was some other way that did not raise an exception.

reply

The Reddest
06/16/2009 - 11:36

You can probably get around it using BeginAcceptTcpClient and EndAcceptTcpClient.

reply

tohox
07/03/2009 - 14:02

Hi,

I've implemented your server solution and it works fine except that threads seem to be accumulating and not being released as the clients close their connection. Everytime a connection is caught by the TcpListener the size of the application in memory grows by a few kB but upon the final tcpClient.Close() in the HandleClientComm the ressources don't seem to released. So my application is constantly inflating... It was my understanding that once the connection was closed the thread would simply vanish?

thanks!

reply

Anonymous
07/05/2009 - 17:05

Hi again its tohox,

So I did my homework thoroughly debugging my app, reading many things about threading and .Net memory management and it appears that this memory inflation is somewhat normal given the way managed code works and how the garbage collector handles ressources.

When hitting the server with many requests per second the memory usage quickly grows to a few MBs more than when the server was first started and it then tends to stabilize. After that it will occasionnaly grow or shrink but stays roughly the same. Forcing the garbage collector to do its job will momentarily free up a few kilobytes but memory usage will eventually crawl back up...

So, false alarm and many thanks for a great tutorial!

reply

Anonymous
08/03/2009 - 19:47

Thank you for the article. This is the first piece i've seen on tcp communication in c# .net. I have a question for you though. Is it common practice to use a blocking loop to wait for client connections? It seems a bit like a duct tape solution to me. Are there no .Listen() methods or anything of that nature? Would a .Listen() method simply wrap a blocking loop? Just seems... i don't know... inelegant?
Thank you again though. Great article. :)

reply

The Reddest
08/04/2009 - 08:52

I like to use the blocking call myself, but there are asynchronous methods that won't require it. Check out BeginAcceptTcpClient and EndAcceptTcpClient.

reply

Rehab
08/13/2009 - 07:44

thanks for this good article so much really i have searched a lot but this was the best
i have a silly question as i am new to network programing
what happen if the accept client has no object to return??

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);
  }
}  

reply

Anonymous
11/23/2009 - 06:33

run your program and place breakpoints at the accept client line and one at the line just after that, you will see that the accept client will not move to the next code line untill a client is connected so the object will not be nothing

reply

Anonymous
08/29/2009 - 02:51

Great article, but how can I use this one when I want to connect to a remote computer on Internet with a router(a local ip adress)

reply

The Reddest
08/30/2009 - 18:53

In this example, the TCP server is listening on port 3000. The router would have to be configured to forward that port to your desired computer.

reply

suchislife801
09/06/2009 - 23:43

What a clean and great sample you've posted. I was just wondering one thing. Would you be so kind to perhaps post the following code updates if its not to complicated:

+ Everytime the server accepts a client, this client is added to a list.

+ Everytime a message is sent to the server, a true or false flag is sent as well telling the server to broadcast the message back to the client who sent it or to all clients on the list of connected clients.

reply

Anonymous
09/08/2009 - 21:26

Great article, thanks for posting this. I have a problem though...

It seems that the server can only be connected to using a client on the same computer as the server or on the same network (intranet).

How do I open the server up to connections from the open internet?

Thanks in advance to anyone who can help me with this issue!

reply

Anonymous
09/12/2009 - 00:52

Here is my code:

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

namespace SimpleConsoleServer
{
    class Program
    {    
        // Global methods
        private static TcpListener tcpListener;
        private static Thread listenThread;
        private string endl = "\r\n";

        /// <summary>
        /// Main server method
        /// </summary>
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 80);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        /// <summary>
        /// Listens for client connections
        /// </summary>
        private static void ListenForClients()
        {
            tcpListener.Start();

            while (true)
            {
                try
                {
                    // Blocks until a client has connected to the server
                    TcpClient client = tcpListener.AcceptTcpClient();

                    // Create a thread to handle communication
                    // with connected client
                    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                    clientThread.Start(client);
                }
                catch (Exception)
                {

                }
            }
        }

        /// <summary>
        /// Handles client connections
        /// </summary>
        /// <param name="client"></param>
        private static void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            do
            {
                bytesRead = 0;

                try
                {
                    // Blocks until a client sends a message                    
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch (Exception)
                {
                    // 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();

                // Output message
                Console.WriteLine("To: " + tcpClient.Client.LocalEndPoint);
                Console.WriteLine("From: " + tcpClient.Client.RemoteEndPoint);
                Console.WriteLine(encoder.GetString(message, 0, bytesRead));

            } while (clientStream.DataAvailable);

            // Release connections
            clientStream.Close();
            tcpClient.Close();
        }
    }
}

reply

Anonymous
09/13/2009 - 18:40

Follow-up:

I resolved the issue. Apparently the corporate domain my computer was joined to had settings which blocked all ports for incoming requests not on the domain.

reply

ash1988
10/21/2009 - 06:26

Hi I've been trying to piece together some code from this tutorial for my application and have come across a few problems.

Can anyone help me out with seeing why I can't send more than one message in either direction with the code I have, and why this would be the case. I get the feeling I've done something seriously wrong!

Thanks for any help.

Server Side

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace TcpTrainServer
{
    public partial class Form1 : Form
    {
        private static TcpListener tcpListener;
        private static Thread listenThread;
        static NetworkStream clientStream;
        static string textFromClient = "";
        //private string endl = "\r\n";

        public delegate void MessageReceivedHandler(string message);
        public event MessageReceivedHandler MessageReceived;

        public Form1()
        {
            InitializeComponent();
            initiateListen();
        }


        private void initiateListen()
        {
            tcpListener = new TcpListener(IPAddress.Any, 8000);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }


        /// <summary>
        /// Listens for client connections
        /// </summary>
        private static void ListenForClients()
        {
            tcpListener.Start();

            while (true)
            {
                try
                {
                    // Blocks until a client has connected to the server
                    TcpClient client = tcpListener.AcceptTcpClient();

                    // Create a thread to handle communication
                    // with connected client
                    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                    clientThread.Start(client);
                }
                catch (Exception)
                {

                }
            }
        }



        private void buttonStartListening_Click(object sender, EventArgs e)
        {
            initiateListen();
        }

        /// <summary>
        /// Handles client connections
        /// </summary>
        /// <param name="client"></param>
        private static void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            //NetworkStream clientStream = tcpClient.GetStream();
            clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            do
            {
                bytesRead = 0;

                try
                {
                    // Blocks until a client sends a message                    
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch (Exception)
                {
                    // 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();

                // Output message
                textFromClient = tcpClient.Client.LocalEndPoint + " " + tcpClient.Client.RemoteEndPoint + encoder.GetString(message, 0, bytesRead);

                //Console.WriteLine("To: " + tcpClient.Client.LocalEndPoint);
                //Console.WriteLine("From: " + tcpClient.Client.RemoteEndPoint);
                //Console.WriteLine(encoder.GetString(message, 0, bytesRead));

            } while (clientStream.DataAvailable);

            // Release connections
            // clientStream.Close();


           

            //tcpClient.Close();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            textBoxMessage.Text = textFromClient;
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            textFromClient = "";
            textBoxMessage.Clear();
        }

        private void buttonSendToClient_Click(object sender, EventArgs e)
        {

            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] buffer = encoder.GetBytes("Hello Server!");
           
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
    }
}





Client Side (User App)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace UserApp
{
    public partial class Form1 : Form
    {
        static TcpClient client;
        IPEndPoint serverEndPoint;
        NetworkStream clientStream;
        static String textFromServer;

        public Form1()
        {
            InitializeComponent();
            iniTCP();
        }

        public void iniTCP()
        {
            client = new TcpClient();
            serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000);
           
       
        }

        public void connectTCP()
        {
            client.Connect(serverEndPoint);
            clientStream = client.GetStream();

            // Create a thread to handle communication
            // with connected client
            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(client);

        }

        public void sendMsg()
        {
            ASCIIEncoding encoder = new ASCIIEncoding();
           
            byte[] buffer = encoder.GetBytes("Testing TCP/IP connection");
            clientStream = client.GetStream();
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            //clientStream.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            connectTCP();
        }

        private void buttonSendMessage_Click(object sender, EventArgs e)
        {
            sendMsg();
        }

        /// <summary>
        /// Handles client connections
        /// </summary>
        /// <param name="client"></param>
        private static void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            do
            {
                bytesRead = 0;

                try
                {
                    // Blocks until a client sends a message                    
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch (Exception)
                {
                    // 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();

                // Output message
                //textFromServer = tcpClient.Client.LocalEndPoint + " " + tcpClient.Client.RemoteEndPoint + encoder.GetString(message, 0, bytesRead);
                textFromServer = tcpClient.Client.LocalEndPoint + " " + tcpClient.Client.RemoteEndPoint + encoder.GetString(message, 0, bytesRead);

            } while (clientStream.DataAvailable);

           
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            // Release connections
            clientStream.Close();
            //tcpClient.Close();
        }

       
   

    }
}

reply

The Reddest
10/21/2009 - 08:14

My only guess is that clientStream.DataAvailable is returning false. DataAvailable only returns true if data is available to be read. Since you're reading all of the data from the stream in the loop, it will most likely revert to false by the time the loop ends.

reply

ash1988
10/21/2009 - 17:17

ok so with that aside, am I right in my understanding that once a "clienstream" has been established between server-client that they can send/receieve using this without any issues with blocking sockets or anything like that?

In your example you have this code to send from server-client

NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

Was I correct in adding a handlecomm method at the client end because how else would the application know how to handle the receival of data?

Im confused in regards to the part where say I go to send a message from client-server, how is it that only the server "handlecomm" and not the client "handlecomm" won't see data in the stream to be read?

Thanks

reply

ash1988
10/22/2009 - 17:56

disregard my last message, I got it working, you were right about the DataAvailable returning false. I've just placed an infinte true loop around the other loop, not sure if thats the best way to get around it but its working!!
Thanks heaps

reply

The Reddest
10/23/2009 - 07:33

You could just replace the inner loop with a while(true) loop. On error conditions you call break, which will correctly exit the loop. If you surround the inner loop with another one, you might have problems getting that thread (and your application) to exit.

reply

Teres
10/27/2009 - 10:33

I have modified a bit client and server, so that server replies to client and they communicate until client types "exit".

CLIENT

Console.WriteLine("Type 'exit' to exit");
            while (true)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("SEND: ");
                buffer = encoder.GetBytes(Console.ReadLine());
                if (encoder.GetString(buffer) == "exit")
                {
                    break;
                }
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("SENDING: " + encoder.GetString(buffer));
                clientStream.Write(buffer, 0, buffer.Length);
                Console.ForegroundColor = ConsoleColor.Red;
                clientStream.Read(buffer, 0, buffer.Length);
                Console.WriteLine("REPLY: " + encoder.GetString(buffer));
            }

SERVER:

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
                Console.WriteLine("RECEIVED: " + encoder.GetString(message, 0, bytesRead));

                //REPLY

                /*sMessage = encoder.GetString(message, 0, bytesRead);
                sMessage = sMessage.ToUpper();
                Console.WriteLine("REPLY: " + sMessage);
                message = encoder.GetBytes(sMessage);
                Console.WriteLine("REPLY: " + encoder.GetString(message, 0, bytesRead));
                clientStream.Write(message, 0, bytesRead);*/

               
               
                /*message = encoder.GetBytes(encoder.GetString(message,0,bytesRead).ToUpper());
                Console.WriteLine("REPLY: " + encoder.GetString(message, 0, bytesRead));
                clientStream.Write(message, 0, bytesRead);*/


                byte[] buffer = encoder.GetBytes(encoder.GetString(message, 0, bytesRead).ToUpper());
                clientStream.Write(buffer, 0, buffer.Length);
                Console.WriteLine("REPLY: " + encoder.GetString(buffer, 0, buffer.Length));
               
                clientStream.Flush();

            }

Can you tell me why only the last "method" in server works ? If I try to do the same thing with two previous "methods", after receiving first message from client and sending it back, server shows that client has disconnected.

On the other hand those two "methods" work fine if I don't try to do anything with buffer (just send it back).

reply

Teres
10/28/2009 - 08:36

Why can't I use the same buffer I received message to ?

reply

Teddy
11/18/2009 - 11:40

I need help urgently.

An application written in C++ writes messages in the form of (char*) struct continuously.

I need to create a windows server ( written in c#) that would receive that message from that socket and parse that and send the information back again in the same socket.

Please help me
1. how the c++ message will be read by c# codes?
2. How the threading model would be for the c# application?
3.How it will write data into socket that would be readable by c++ application?

PLeeeeeASE HELP.

reply

Anonymous
01/06/2010 - 18:22

C# will have no problem receiving CPP char*s (they point to char[]) and CPP will have no problem receiving C# char[]s, it depends on your methods for retrieving data.

Perhaps something more "beginnerish" would be beneficial before tackling threading and sockets..

reply

the person with the toothpaste tube
12/09/2009 - 18:26

excellent tutorial

reply

the person with the toothpaste tube
12/09/2009 - 18:27

Console.WriteLine("Thank you for the tutorial.");

reply

Shankar S
12/10/2009 - 22:05

is there any way to test the connectivity(telnet or ping) using C# .net if we enter the source(usually not the machine logged in) ip port and destination ip port in a simple form?

Thanks in Advance.

reply

Anonymous
07/21/2011 - 14:19

Agreed

reply

sonea
12/21/2009 - 10:01

Hello. Need your help!
In the article you've said that you usually save collection of TCPClient. Is there any way to detect the client is discinnecting?
Thanks for any advices!

reply

The Reddest
12/21/2009 - 10:09

Yes, clientStream.Read(message, 0, 4096), will throw an exception (probably IOException), which indicates the underlying socket has been closed.

reply

sonea
12/22/2009 - 02:58

Thanks a lot! I'll try this.

reply

Annonimous
12/30/2009 - 03:01

Hello,

how do you stop the server? I mean, your Read call has Infinite timeout so the call will block forever.

Then, how do you can stop the server if you need to?

reply

Anonymous
01/26/2010 - 13:36

This stuff looks interesting although I can't seem to get any of the examples to compile in Visual Studio 2005.

Can anyone post a complete compileable example of the client and server app where data communicated between the client and server is displayed in a form control?

reply

kami
02/07/2010 - 23:31

Hello everyone,
I am new in Socket programming, I want to send file in chunks from server to client side. As server send packet(packetID + SizeofPacket + Data) to client side, Client save the data in buffer and send the response(packetID) back to server. then server looks the packetID and send the datachunk related to packetid.
Can I achieve this by using TCP sockets. Can someone explain me how. Thanks

reply

webmartians
02/09/2010 - 14:52

Curiosity: the example starts a thread to handle the communications and provide the "intelligence" (HandleClientComm).

What about using AcceptTcpClient (which blocks until a connection is available) - acquiring the entire message - and then spawning a thread to provide the process? Yes, the acquisition of the message is then in-line, but, if I read my TCP specs correctly, it will always be in-line because of the buffers.

For example:

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
...
TcpListener lr /*Listener*/ = new TcpListener(IPAddress.Parse(InternetProtocolAddress), InternetProtocolPort);
for (lr.Start(); MyListenerIsNotShutDown);)
{
   TcpClient cl /*Client*/ = lr.AcceptTcpClient();
   byte[] bf /*Buffer*/ = new byte[8192];
   string mg /*Message*/ = string.Empty;
   NetworkStream sm /*Stream*/ = cl.GetStream();
   for (int ct = sm.Read(bf, 0, bf.Length - 1); 0 < ct; ct = sm.Read(bf, 0, bf.Length - 1))
      mg += Encoding.ASCII.GetString(bf, 0, ct);
   mg = mg.Trim();
   try
   {  // Start a new thread to process this message.
      Thread thd /*Thread*/ = new Thread(new ParameterizedThreadStart(MyMessageProcessor));
      thd.Start(mg);
   }
#pragma warning disable 168
   catch (OutOfMemoryException ex /*Exception*/)
   {  // There is not enough memory to start the thread: do it in-line, thereby, throttling responses.
      MyMessageProcessor(mg);
   }
#pragma warning restore 168

...public static void MyMessageProcessor(object prmMsg)...

Just to add to the confusion, the send is therefore stateless:

TcpClient cl /*Client*/ = new TcpClient();
cl.Connect(new IPEndPoint(IPAddress.Parse(prmAdr), prmPrt));
ASCIIEncoding ec /*Text Encoder*/= new ASCIIEncoding();
byte[] bf /*Buffer*/ = ec.GetBytes(prmMsg);
NetworkStream sm /*Stream*/ = cl.GetStream();
sm.Write(bf, 0, bf.Length);
sm.Flush();

reply

webmartians
02/22/2010 - 16:19

Never mind... Don't do it (spawn the thread AFTER acquiring the text)... The newer Windows TCP stacks do indeed provide for multiple, concurrent connections' queues being drained.

reply

khan
02/17/2010 - 10:21

Hello, is it possible that 2 clients connected to same server can communicate each other using c# multithreading programming?? Thanks... I need help

reply

webmartians
02/22/2010 - 16:31

The server merely receives and replies to clients; client to client communications are not possible ... strictly speaking.

I suppose you could write your server's message handler to recognize some kind of forwarding command prefix in the message (eg: "To 12.34.56.78:50000"). The sending client would have to put that it its message. However, that brings up the question, "If the client knows the IP address and port of the other client, why is it not sending the message directly?"

reply

khan
02/23/2010 - 13:08

Hi, I am writing Bluetooth simulation program in c#. I am writing two clients as Master and Slave device. and one server application which act as a channel between Master and Slav device. so, Master communicate with Slave through Channel. Later I will add interference at channel application and see the effects on Master and Slave, as these Master sending a big file in chunks to Slave.
Please I need your's suggestions, how I achieve this???
Thanks
Khan

reply

mrRumble
03/01/2010 - 21:20

hii, how to receive and send data to linux client from .NET using format

struct tcpdata {
unsigned long code;
unsigned char msg[256];
}

thanks,

reply

webmartians
03/11/2010 - 09:32

I got most of this working ... in a "harsh" environment (slow processors at both ends, zilch memory). Here is what I learned:

1- recv returns zero when its current crop of buffers for the connection are empty. THAT DOES NOT MEAN THE MESSAGE IS FULLY ACQUIRED! Maybe everybody else got this; I didn't and had to add an endian-independent, length field at the beginning of each message.

1b- mrRumble - "On the nose!" (length field at the beginning of each message) ... except that there are a number of machines of different "endianness" that do not store the bytes of an unsigned long in the expected order (assuming you want to talk to not just C# nodes). You must replace that unsigned long (or long) with four, distinct byte values, where you know that the first one is the high-order, and so on (or whatever order you want, as long as it's consistent).

2- When the client (sending) side is C# and the server (receiving) side is C/C++, when the C# closesocket executes, unread data at the server (C/C++) side (or, maybe, still in flight) is destroyed ... sometimes ... often enough to be catastrophic. Strangely enough, this does not seem to happen in reverse (C/C++ client sending to a C# server). I found two WWW reports of similar behavior - "fire and forget" is not a good philosophy, here. The answer is to require some kind of acknowledgment for every transmission (for example, an empty message) before the sender executes closesocket.

3- The idea of the loop around the server's loop is a real frustration-preventer: having the code able to say, "This failure is too nasty for me to handle in the inner loop; I'll reset and restart everything!" definitely makes unit testing more pleasant. I suggest a Sleep of a good second or so at the end of the outer loop:
if (this is not a shutdown) Sleep(1000);
to give the system some cycles to tidy whatever messes it needs to clean up and, maybe, restore resources that will allow the next, major cycle of your server to execute successfully.

4- Consider UDP instead of TCP. If you can do what you need to do in UDP, use it instead of TCP. Remember, UDP blasts your packets all over the place: they WILL arrive out of order. You'll need, instead of just a length field, a (packetN)/(ofMpackets) field in each transmission. ...but UDP is much faster, simpler, and, oddly enough, can end up being more robust than TCP. Hard to swallow, I know, but that has been our experience: UDP gets more data through bad pipes than TCP does.

...hope this saves somebody some grief...

reply

milop
03/16/2010 - 06:10

If each thread is communicating through the same port, how is it that one client doesn't get the data intended for a different client? Does the NetworkStream object create the "isolation"?

reply

The Reddest
03/16/2010 - 08:49

When a connection is made, a socket will be formed between the server and the client. Each port can have several active sockets. The .NET framework and the OS maintain this information.

http://www.freesoft.org/CIE/Course/Section4/6.htm

http://en.wikipedia.org/wiki/Internet_socket

reply

milop
03/18/2010 - 05:50

Thanks. After a bit of a brush up on sockets I confirmed this with NETSTAT.

I have one more question, if you don't mind. In your article you stated that you like to keep the "client" object around. How would you know that a "client" object can be reused? The "Connected" property?

Thanks again.

reply

The Reddest
03/18/2010 - 08:30

I've never reused a TcpClient object. In the example code, the client only lives in the scope of its thread. There's no way for the server to find a client when it's needed. What I meant by "keep it around" was to put it in some sort of collection so the server can look up a client when it needs to send it something.

reply

milop
03/18/2010 - 12:08

Understood. What do you mean by "send it something" and when would you know that it's ok to send it something? I mean, what mechanism would you use to determine that the client object is no longer exchanging information and is in a state for you to send it something?

reply

The Reddest
03/18/2010 - 12:49

There's nothing special required to know when you can send the client information. Simply surround the Send function with a try-catch. If Send throws an exception, that client has disconnected.

As for "send it something", let's say we're building a chat client. You've got two clients connected to the server and they want to communicate with each other. One client sends a message to the server that needs to be relayed to another client. Somehow you've got to find the client to relay the message to. The message might contain a user ID, which you'd associate with each client using a dictionary - or something similar.

reply

milop
03/18/2010 - 13:07

Ok, I see what you had in mind.

My server needs only to exchange info with a single client and then end. The threads that I shell out are cleaned up once the socket is closed, usually in about 30 seconds or so (I also close the stream object, you don't).

I guess because I'm not keeping them in some container there is no reference to it and the GC cleans it up. Would you agree?

Thanks again,
Mike

reply

pollardomax
04/02/2010 - 08:23

Thanks the tutorial is great, I've got it working...
I would need to send data from the server to all the connected clients.. is there any simple way to do this in your example?

reply

goldenfox
04/04/2010 - 07:31

@The Reddest: Can you give me an idea on how to use this method to allow the server to send data(possible huge data) to coming from mysql to the clients connected to it? I would like to use this technique to create something like a middleware between clients and mysql server.

Thanks,

goldenfox

reply

AliBaba
04/10/2010 - 05:01

When My code is in clientStream.Read(...) loop and how can I break it? Can I set a ReadTimeout such as SerialPort.ReadTimeout?

Thanks

reply

topagent006
04/16/2010 - 14:37

what is the maximum connection can I have using this chat method? Is it limited by the OS in term of threads it can have? What could be other limitations?

Thanks

reply

The Reddest
04/16/2010 - 15:22

There's basically no limit outside of your computer's resources. Memory, threads, and available handles. A normal desktop should be able to handle a least a thousand.

reply

topagent006
04/16/2010 - 22:51

Wow. Thank you for your prompt reply.

reply

ravik
04/22/2010 - 05:11

Hi ,
Thanks for posting the tutorial.
I need some information for sending and receiving messages through telnet using tcp connection after the connection and the valiadation of the login string.and the data will be storing in the log file and the listbox in mainform.
can anybody help me how can i solve this issue.

reply

samad
04/22/2010 - 11:24

Hi,

you put great stuff on this page... as i can see in above example using TCP .. Does TCP client create one seperate thread on TCP listener server and thumb of rule there shouldnt be processor*2>running thread on server side..

i saw some articles where they explain select and pooling technique for nonblocking server...and they used socket class rather thn TCP

i am trying to implement one server which can serve thousands of clients ... do you have any good example or article regarding that

Thanks in Advance

reply

lou
05/06/2010 - 15:16

Hi,thanx for your good tutorial.

here is question as Nigel asked it long ago. i have the same problem.and i could not fine the answer,can any body help me.

I have an application which is essentially a TCP/IP Server to which up to 16 clients can connect at any one time each on it's own unique port, i.e. 4001 - 4016.

The connections establish ok but after a period of time the connections seem to disconnect and I'm not sure why. when you run NETSTAT from the DOS Prompt it shows the connections in a CLOSE_WAIT state.

The clients then have to reconnect... and so the loop goes on...

Whe I try to write back to the client and it is disconnected I get an error code of 10053 which means that the software in the host machine has disconnected or something along those lines.

Has anyone else had experience of this? Could it be a timeout? How can I ensure that once my server accepts a client connection that it helps to maintain the established connection?

Any and all help appreciated.

Nigel.

reply

The Reddest
05/06/2010 - 15:26

I don't know what could be causing it, and it's something I've not experienced. I checked the documentation for TcpListener and TcpClient, and their timeouts are all initialized to infinite.

reply

Bubba
05/07/2010 - 14:23

This is a really great example and I have a working implementation. Thanks. One thing I can't seem to wrap my head around though.

In the scenario you have covered, a client sends a message to the server and the server responds. How do you set up for a scenario where the server can also send a notification to the client. The client would always have to be in a listening state (ie: bytesRead = clientStream.Read(message, 0, 4096); ) which would cause issues when the client sends a command and is waiting for a response from the server.

Would I need two connections to handle this or is there a more elegant way to accomplish this ?

reply

The Reddest
05/07/2010 - 15:59

If the client sends a request and is waiting on a response, there's no guarantee that the notification won't be received before the response.

This scenario should be handled in whatever protocol you've designed for communication. Typically people reserve the first few bytes for the type of message being transferred. So if the client is waiting for a response of type n, and receives a different message type, it can process the notification and continue waiting for the message.

reply

lou
05/07/2010 - 14:58

Thank you very much.

reply

lou
05/08/2010 - 11:06

void main (Hi...arg,events,help)
{
i want to save tcpclient in a collection i used Hashtable and then use an array of TcpClient but when server want to send data t specific client with specific ConnectID it say that can not use dispose object
it means that the tcpclient that i saved in server is disconnected.client.(connected==false) i think my previouse problem has the same source as this is.
so if im am wrong in saving client how should i do that.and be able to send info from server to specific client.
[edit post]
after i post this i found that the thread that this client has run on it(also other client on their own thread) is stoped.and i think this is the source of error 10053 software in you host disconnect you.(sth like that).but i dont know why the threds stop afterward.and i also geuss it might be time out problem as you sais it is finite but as i trace and load connection from collectio at first it is connect but after seconds as i stay in Isend() it will disconnect and my stream writer can not write to dispose object so if the problem is from timeout how should i do that.
so any buddy has any idea,
thanx 4 ur help;

and here is the code.

}
here is my server class and send function

    class Server : packetizer
    {
        #region Variable Scope
        private Socket socket;
        private TcpListener tcpListener;
        private Thread listenThread;
        private Queue thread_Queue;//it keep thread id inorder to dispose after disconnection
        private delegate void setText(string str);
        private TextBox Logger;
        private static int ConnectID;
        private Connection_State CS;
        #endregion

        public Server(TextBox logger,Connection_State cs) //Constructor
        {
            Logger = logger;
            CS = cs;
        }
       
        public void start_Server() //Point to start Server
        {
            this.tcpListener = new TcpListener(IPAddress.Any, 1313);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));
            this.listenThread.Start();
        }
       
        private void ListenForClients()
        {
            this.tcpListener.Start();
            Invoking_Logger("Server startlistenning...");
            thread_Queue = new Queue();
            TcpClient client = null;
            while (true)
            {
                try
                {
                    //blocks until a client has connected to the Server
                    client = this.tcpListener.AcceptTcpClient();
                }
                catch (SocketException ex)
                {
                    break;
                }
               
                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                //thread_Queue.Enqueue(clientThread);
               
                clientThread.Start(client);
               
                socket = client.Client;
                CS.ClientHolder.structSocket = client.Client;
                CS.ClientHolder.structThread=clientThread;
                CS.ClientHolder.structTcpClient = client;
                CS.Add_To_Acp_Client((ConnectID+1), CS.ClientHolder);

                Invoking_Logger("Client with below information registerd to server:\r\n" +
                    ((IPEndPoint)(socket.RemoteEndPoint)).Address.ToString() + "::" + ((IPEndPoint)(socket.RemoteEndPoint)).Port.ToString()+"\r\n"+
                     "SocketType: " + socket.SocketType.ToString() +"\r\n" +SocketOptionLevel.Socket.ToString() + " " +SocketOptionName.IPOptions.ToString());
            }
        }

        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            Packet rcvPacket = new Packet();
            Packet sendPacket = new Packet();
            IPEndPoint ipe = (IPEndPoint)tcpClient.Client.LocalEndPoint;
           
            byte[] DataToSend;
            byte[] message = new byte[tcpClient.ReceiveBufferSize];
            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;
                }
               
                //---get the message---
                byte[] buff;
                string MessageReceived =
                    ASCIIEncoding.ASCII.GetString(message, 0, bytesRead);
                rcvPacket = (Packet)RawDeserialize(message);

                Invoking_Logger(MessageReceived.ToString());

                switch (rcvPacket.Type)
                {
                    case "0"://It is usual msg 4 Connection
                        if (rcvPacket.ProcID == -1)
                        {
                            try
                            {
                                Interlocked.Increment(ref ConnectID);
                                sendPacket.Type = "1";
                                sendPacket.Message = "You have registerd";//CS.Get_INFO;
                                sendPacket.IP_Addr = Convert.ToString(ipe.Address);
                                sendPacket.Port_NO = ipe.Port;
                                sendPacket.ProcID = ConnectID; //CS.Set_ConnectID;
                                DataToSend = RawSerialize(sendPacket);//ASCIIEncoding.ASCII.GetBytes(t);
                                tcpClient.GetStream().Write(DataToSend, 0, DataToSend.Length);
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("Item Exist");
                            }
                         
                        }
                        break;
                    case "1"://Ack msg
                        break;
                    case "2"://register for Item processing

                        bool bol = false;
                       
                        break;

                    case "UDP_BroadCast":
                        break;
                    default: break;
                }
                //message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();
                System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
            }

            tcpClient.Close();
        }
        public void Isend(int ConnectID)
        {
            Socket SockettcpClient=null;
            TcpClient tcpClient = null;
            CData cData=new CData() ;
            Packet pck_Test = new Packet();
            pck_Test.Type = "1";
            pck_Test.Message = "test message";
            byte[] buffer = RawSerialize(pck_Test);
            try
            {
               cData=(CData) CS.Find_In_Acp_Client(ConnectID);
               
            }
            catch (Exception ex)
            { }
            tcpClient =(TcpClient) cData.structTcpClient;
            Thread thrd = cData.structThread;
            thrd.Start();
            NetworkStream clientStream = tcpClient.GetStream();
            //ASCIIEncoding encoder = new ASCIIEncoding();
            //byte[] buffer = encoder.GetBytes("Hello Client!");

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            clientStream.Close();
        }

and here is COnnection stat class that hols my client information to reconnect to them i

 

 public struct CData
    {
        public Socket structSocket;
        public TcpClient structTcpClient;
        public Thread structThread;
    }


    class Connection_State
    {
        #region Variable Scope
        private Hashtable Accepted_Client = new Hashtable();
        public CData ClientHolder = new CData();
        #endregion

        public Connection_State()
        {

        }

        public Hashtable Acp_Client
        {
            get { return Accepted_Client; }
            set { Accepted_Client = value; }
        }

        //Add new client that connect to sever to this HashTable
        public void Add_To_Acp_Client(int ConnectID, CData structtcpthread)
        {
            Accepted_Client.Add(ConnectID, structtcpthread);
        }
}

reply

Perry
05/09/2010 - 11:32

Don't know if I'm asking the same as the guy above me, but I'm asking it more simple anyway. How do I send to all connected clients? I've tried adding all tcpClients to a list and I tried to send to their streams, but unfortunatly I don't recieve a thing in my client, while I can send data back to a single client upon connection...

Here's the 'sending' code:

public void sendToClient(String line, TcpClient client)
        {
            try
            {
                NetworkStream stream = client.GetStream();
                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] buffer = encoder.GetBytes(line + "\0");

                stream.Write(buffer, 0, buffer.Length);
                stream.Flush();
            }
            catch
            {
                connClients.Remove(client);
                myInterface.logTxt.Invoke(new AppendTextDelegate(writeIntoLog), ("Client Disconnected."+Environment.NewLine));

            }
        }

        public void broadcast(String line)
        {
                for (int i = 0; i < connClients.Count; i++)
                {
                    sendToClient(line, connClients[i]);
                }
                myInterface.logTxt.AppendText("Message broadcasted to " + connClients.Count.ToString() + " clients." + Environment.NewLine);
                }
}

reply

Benio
05/22/2010 - 12:20

Hi,

I've made an application "client -> server communicator" made your way from the tutorial(btw.I LOVED IT!! All you need in an excellent compact form. Thank you for it!). I use it to send over a message to a PC in my company to start backuping itself. Everything works fine when I connect client and server to my router in the room, but when I take the PC for backuping downstairs where it belongs the server responds something similar to "Connection cannot be made as the server actively refuses it." The machines ping fine! I work in a large company with proxies and stuff and I assume the problem is the IT security, if so, how can I make the connection between the 2 PCs? - I really wouldn't want to involve IT "experts" responsible for security here to do it, as it would be done after 2012, and it'd be too late because it'd be after the end of the World :)

ps. Thank you for the tutorial. If the application works maybe I'll get a raise :)

Cheers,
Benio

reply

Feez
06/18/2010 - 12:02

I am in trouble. Is it possible that same client and same server creates mutiple connection. Because i need to know the status of same client multiple request response from server. so that there won't be any business loss.

reply

cdutoit
07/25/2010 - 16:49

Hi,

I am trying to send an acknowledgement back to the client once they have sent a message to the server.

I where should I add the code below to the HandleClientComm to get it working?

byte[] buffer = encoder.GetBytes("Hello Client! Message Received!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();

HandleClientComm

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();
}

The listener on the client does not pick anything up if I just add it below the

 
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));

Not sure what I am missing?

reply

MRB
08/01/2010 - 01:10

thank you for tutorial but in this part

client.Connect(serverEndPoint);

it has error
no connection could be made because remote machine refused it

can someone help me?

reply

MRB
08/01/2010 - 02:52

sorry, I had stupid mistake :)

reply

anonhj
09/21/2011 - 01:03

hello, i face the same problem as well, how you solve it? can tell me??

thanks..

reply

fwsteal
08/04/2010 - 11:41

i read the article and seems good; have a question about getting the data back from the server. How do i do that?

I have two code files below:

client form -- windows form with a textbx for remote ip address and port; button for connect to device; status txtbox based on connection; message txtbx to send to remote sever; send button; message received txtbox.

client.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Net.NetworkInformation;

namespace TCPServerTutorial
{
    public partial class Client : Form
    {
        IPAddress ip;
        const int port = 1234;
        string myIP = string.Empty;
        string strMode = string.Empty;
        string strAddress = string.Empty;

        TcpClient client = new TcpClient();
        Server server = new Server();

        public Client()
        {
            InitializeComponent();
            txtbxIPAddress.Text = "192.168.10.147";
            txtbxPort.Text = "1234";
        }

        private void txtbxConnectToDevice_Click(object sender, EventArgs e)
        {
            //get the remote IP address
            IPAddress address = IPAddress.Parse(txtbxIPAddress.Text.Trim());
            int port = System.Convert.ToInt16(txtbxPort.Text.Trim());

            //create the end point
            IPEndPoint serverEndPoint = new IPEndPoint(address, port);

            client.Connect(serverEndPoint); //connect to server

            if (this.client.Connected)
            {
                txtbxConnectionStatus.Text = "Connected";
            }
            else
            {
                txtbxConnectionStatus.Text = "Not Connected";
            }
        }

        private void btnSendMessage_Click(object sender, EventArgs e)
        {
            NetworkStream clientStream = client.GetStream();

            ASCIIEncoding encoder = new ASCIIEncoding();
            string text = txtbxMessageToSend.Text.Trim();

            byte[] buffer = encoder.GetBytes(text); //send a message

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();

            server.MessageReceived += new Server.MessageReceivedHandler(Message_Received);

        }

        void Message_Received(string message)
        {
            //update the display using invoke
            txtbxMessageReceived.Text = message.ToString();
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            client.Close();
            Application.Exit();
        }
    }
}

server.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace TCPServerTutorial
{
    class Server
    {
        //a simple threaded server that accepts connections and read data from clients.
        private TcpListener tcpListener; //wrapping up the underlying socket communication
        private Thread listenThread; //listening for client connections
        const int iPort = 3000; //server port

        public Server()
        {
            this.tcpListener = new TcpListener(IPAddress.Any, iPort);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));
            this.listenThread.Start();
        }

        private void ListenForClients()
        {
            this.tcpListener.Start(); //start tcplistener

            //sit in a loop accepting connections
            while (true)
            {
                //block until a client has connected to the server
                TcpClient client = this.tcpListener.AcceptTcpClient();

                //when connected - create a thread to handle communication with a connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                //pass the tcpclient object returned by the accepttcpclient call to our new thread
                clientThread.Start(client);
            }
        }

        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client; //cast client as a tcpclient object
            //because the parameterizedthreadstart delegate can only accept object types.

            //get the network stream from the tcpclient - used for reading
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            //sit in a true loop reading information from the client
            while (true)
            {
                bytesRead = 0;

                try
                {
                    //block until a client sends a message and is received
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch (Exception ex)
                {
                    //a socket error has occurred
                    throw ex;
                    //MessageBox.Show(ex.Message);
                    //break;
                }

                if (bytesRead == 0)
                {
                    //the client has disconnected from the server
                    //MessageBox.Show("The client has disconnected from the server.");
                    break;
                }

                //message has successfully been recieved
                ASCIIEncoding encoder = new ASCIIEncoding();
                string smessage = encoder.GetString(message, 0, bytesRead);
                if (this.MessageReceived != null)
                    this.MessageReceived(smessage);

                //System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
                //MessageBox.Show(encoder.GetString(message, 0, bytesRead));


                //send data back to client
                //use the tcpclient object to send data back to client
                //byte[] buffer = encoder.GetBytes("Hello");
                //clientStream.Write(buffer, 0, buffer.Length);
                //clientStream.Flush();
            }

            //close
            tcpClient.Close();
        }

        public event MessageReceivedHandler MessageReceived;

        public delegate void MessageReceivedHandler(string message);
    }
}

Any help would be great. Thank you.

reply

Anon999
08/17/2010 - 00:12

Hi.

Thank you for an excellent example!

However, I am having a problem, I want my server to send a short string to each client as they connect to the server, but I keep getting this error on "NetworkStream.Write":

Specified argument was out of the range of valid values.
Parameter name: size

Here is my code:

    class Network
    {
        private const int bufferSize = 8192;

        private IPEndPoint serverEndPoint;
        private TcpClient tcpClient = new TcpClient();
        private NetworkStream netStream;
        private Thread receiveThread;

        public delegate void MessageReceivedHandler(string message);
        public event MessageReceivedHandler MessageReceived;

        public Network(string ServerAddress, int ServerPort)
        {
            try
            {
                serverEndPoint = new IPEndPoint(IPAddress.Parse(ServerAddress), ServerPort);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        public bool ConnectToServer()
        {
            try
            {
                tcpClient.Connect(serverEndPoint);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            netStream = tcpClient.GetStream();

            receiveThread = new Thread(new ParameterizedThreadStart(receiveMessages));
            receiveThread.Start();

            return true;
        }

        private void receiveMessages(object Message)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] buffer = new byte[bufferSize];
            int bytesRead = 0;

            while (true)
            {
                bytesRead = netStream.Read(buffer, 0, bufferSize);
                if (bytesRead > 0)
                {
                    string message = encoding.GetString(buffer);

                    if (this.MessageReceived != null)
                        this.MessageReceived(message);
                }
                buffer = encoding.GetBytes("user");
                netStream.Write(buffer, 0, buffer.Length);
                netStream.Flush();
                break;
            }
            while (true) ;
        }
    }

I have been googling, but not been able to find anything that would explain why I keep getting that error.

Thankful for any help you can give me!

reply

Anon999
08/17/2010 - 00:37

Ahhh, too early in the morning here for me ;)

Here is my server code:

    class Network
    {
        private const int bufferSize = 8192;

        private TcpListener tcpListener;
        private Thread listenThread;

        List<Thread> clientThreads = new List<Thread>();
        List<TcpClient> clientList = new List<TcpClient>();

        public delegate void ConnectionEstablishedHandler(TcpClient tcpClient);
        public event ConnectionEstablishedHandler ConnectionEstablished;

        public void StartListening()
        {
            tcpListener = new TcpListener(IPAddress.Any, 3333);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        public void StopListening(bool DisconnectAll)
        {
            tcpListener.Stop();

            if (DisconnectAll)
            {
                foreach (TcpClient tmpClient in clientList)
                {
                    tmpClient.Close();
                }
            }
        }

        private void ListenForClients()
        {
            tcpListener.Start();
            TcpClient tcpClient;
            while (true)
            {
                try
                {
                    tcpClient = tcpListener.AcceptTcpClient();
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                    break;
                }
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
                if (this.ConnectionEstablished != null)
                    this.ConnectionEstablished(tcpClient);
                clientList.Add(tcpClient);
                clientThread.Start(tcpClient);
            }
        }

        private void HandleClient(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream netStream = tcpClient.GetStream();
            bool clientDone = false;

            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] buffer = new byte[bufferSize];

            //Request identification from the recently connected client.
            buffer = encoder.GetBytes("identify");
            try
            {
                netStream.Write(buffer, 0, buffer.Length);
                netStream.Flush();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                clientDone = true;
            }

            while (!clientDone)
            {
                int bytesRead = 0;

                try
                {
                    if (netStream.DataAvailable)
                    {
                        bytesRead = netStream.Read(buffer, 0, bufferSize);
                    }
                }
                catch (Exception e)
                {
                    throw;
                    //MessageBox.Show(e.Message);
                    //clientDone = true;
                }
                if (bytesRead > 0)
                {
                    MessageBox.Show(encoder.GetString(buffer, 0, bytesRead));
                    clientDone = true;
                }
            }
            StopListening(true);
        }
    }

reply

The Reddest
08/17/2010 - 08:43

I noticed a potential problem in your code. You allocate buffer to the size of 8192, then immediate set the reference equal to the output of encoder.GetBytes. Next, while reading from the client, your attempting to read 8192 bytes into a buffer that's now much smaller.

reply

tleylan
08/19/2010 - 11:41

Just a quick note to offer a solution to the blocking call to AcceptTcpClient(). The TCPListener class has a Pending() method indicating whether there is a client to accept.

I added a Boolean property "listening" to control the loop (rather than using "true"). Inside the loop there is a call to Pending() and only if that returns true is there a call to AcceptTcpClient() which should not block.

When you need to stop the server set Listening to false. The loop exits and we an opportunity to call tcpListener.Stop().

Log files confirms that it is working for me...

reply

Anonymous
09/06/2010 - 22:09

I just want to share what I'm doing. I made a chat program/application(with GUI) using C#.NET and I used your codes as reference, it's working fine. I don't actually have an error or problem with my codes. I used the server as bridge only and I can broadcast messages sent from one client to all clients connected. Then I modified it, added some feature and made it work like yahoo messenger or skype but for a local area network only. I have login, registration and I am now working for private messages and adding friends(accepting or rejecting requests). Clients can only use the application if the server is executed on my computer because the ip I set for the clients is my ip.

Now, I have some questions. Is it possible to broadcast the server's IP so that I won't use a default/fixed ip address for the clients to connect? If yes, how will the clients get/search the server's ip? If I want to make another chat application and I want to make it that it won't matter who logs in first, will it be possible to make every client the server themselves? How will they connect to each other? I already had done this using VB6 but with the use of winsock.

reply

Massi636
10/11/2010 - 03:47

Stop problems; this is may way after have read all posts:
added  server.Stop() that simply do a this.tcpListener.Stop(); from the closing event of the main form. Then added  List<TcpClient> clientList = new List<TcpClient>(); and added a client in my collection each time a clientThread.start(); then catch the exception in the while(true) and close all client in the list. I suggest to check with processExploer: it's working fine! Many thanks!

reply

Hans
11/09/2010 - 12:29

This is a good article and still valid today. But you should use the ThreadPool instead of creating a new Thread every time when listening. This will reduce a lot of stress when receiving messages and it will prevent the CLR from having to perform many garbage collections due to a lot of discarded threads.

reply

The Reddest
11/09/2010 - 13:36

In most cases you are correct. The ThreadPool does have a limited number of threads (this can be changed). If the app is handling hundreds or thousands of clients, the ThreadPool will queue your request indefinitely until a thread becomes available - which may never happen if clients aren't disconnecting.

reply

ak.naser
11/20/2010 - 01:29

Your program is well work in local net work. but failed in internet.

reply

ak.naser
11/20/2010 - 01:31

i want a clear article for TCP server / Client run over inter net any one help me

reply

Anonymous
11/21/2010 - 11:55

The Reddest,

How can I send some data back to a client and then read that data?

I can't seem to get the code you supplied to work. Could you provide some working example code for me to study please?

Thanks.

reply

Francisco
11/22/2010 - 20:14

Excellent tutorial. Do you have something similar for a threaded client?

reply

Mauricio Sierra
11/27/2010 - 11:52

Gracias men! me sirvió mucho! excelente ejemplo para empezar a programar! Como puedo hacer mas segura la conexión TCP para evitar hackers?

Thanks man! served me! excellent example to start programming! How I can make more secure TCP connection to prevent hackers?

reply

anvas
12/09/2010 - 05:17

Hi,

u guys amazing
Advance Thanks

reply

Anonymous
12/16/2010 - 11:33

Nice! And easy to package with a NotificationAreaIcon application so that everything is not just available at your fingertips, but its activity is visible just by changing the icon! A nice little addition would be including a named pipes server both client-side and server-sode, so that you can not just run information around from machine to machine, but target other objects on any specifc machine that listen to the pipe server.

reply

Joe
12/23/2010 - 01:19

The first comment was over 3 years ago and they've been ticking away ever since. It's not just that the code is clear, it's that the explanations were written clearly too. Excellent work!

I loathe the trite "help me write tcp server program! give me code!" comments. Many questions can be answered by reading through the comments before you post. Although, after 3 years that's getting a bit time consuming. :)

reply

Anonymous
01/15/2011 - 21:07

Any working examples of client reading/receiving data from server..??

I think I have the right code for the server to send data, but not sure how or what event the client uses to receive.

Thanks

reply

rkrijger
01/27/2011 - 06:20

Thank you for this great example! I found it to be very useful. A few questions will arise, though:

Why not use:

private void HandleClientComm(TcpClient client)

Instead of

private void HandleClientComm(object client)

?!?

reply

rkrijger
01/27/2011 - 06:27

Never mind...
It doesn't compile with "TcpClient" instead of "object".
Sorry.

reply

Anonymous
02/02/2011 - 14:26

how I can create a tcp server in c # .Net using MFC serialization of messages

reply

AnonymousFF
02/02/2011 - 14:42

how I can create a tcp server. Net c # receive and reply to messages MFC serialization

reply

Agehack
02/15/2011 - 05:45

i'm using oscar protocol as used in icq. it's so easy to send ANy data any length with FLAP format.
good article. =)

reply

boyparka
03/16/2011 - 14:26

Hi there,

Just a quick thanks for an excellent tutorial. It helped me out a lot.

reply

santhosh
03/24/2011 - 01:37

hey first of all excellent tutorial.
I am trying to create a GUI socket server.

The goal is simple.

1.Open a port
2.keep sending data to the port
3.the data is given from a textbox in the gui and must be sent after the button is pressed.
4.Do NOT CLOSE THE CONNECTION to the port until a button is pressed in the GUI.

I have done some part of it but the problem i m facing with my code is i am not able to split the accept client connection part from the send data to client part.

Hence each time i click my button to send the data i have to close the connection and open a new connection again. Please help me with this. The code below executes on button press. As you can see each time i have to close the socket and redo everything on each button press. I am not able to split it into parts. Please help me.

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

IPEndPoint ip = new IPEndPoint(IPAddress.Any, 9999);
           
            socket.Bind(ip);
            socket.Listen(10);
            Console.WriteLine("Waiting for a client...");

Socket client = socket.Accept();
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
            cliStatusLbl.Text = "Connected with Client";
           
         
                string sndCmd = "|" + this.keyTxt + "|" + this.valTxt + "\n";
               
                byte[] data = new byte[1024];
                data = Encoding.ASCII.GetBytes(sndCmd);
               
                client.Send(data, data.Length, SocketFlags.None);
                Thread.Sleep(2000);
           
            client.Close();
            socket.Close();

reply

David S
03/26/2011 - 22:04

I solved the same thing using the asynchronous calls built into the object. This will leverage the thread handling built into .Net and you should have less issues with hanging threads. I tested this as part of a HTTP handling program and it was lightening fast and definitely was using multiple connections at the same time.

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

/// <summary>
/// Multithreaded  routine to handle concurrent Tcp connections on a single endpoint
/// </summary>
public class TcpHandler
{
    public bool listening;
    public TcpListener listener;
   
    public void Main()
        {
                Byte[] ip = {127, 0, 0, 1};
        IPEndPoint endPt = new IPEndPoint(new IPAddress(ip), 3000);

        this.listener = new TcpListener(endPt);
        this.listener.Start();

        Console.WriteLine("Listening");

        this.listening = true;
        listener.BeginAcceptTcpClient(HandleRequestAsync, null);

        Console.WriteLine("Press 'Enter' to exit...");
        Console.Read();
        listening = false;

        listener.Stop();
        }

    public void HandleRequestAsync(IAsyncResult ar)
    {
        TcpClient client;

        client = listener.EndAcceptTcpClient(ar);
        if (listening)
        {
            listener.BeginAcceptTcpClient(HandleRequestAsync, null);

        }

        // Handle the client connection here
    }
}

reply

Gulshan Garg
03/30/2011 - 01:31

Hey Dear,
Please send me a server side code to communicate with client, get data from client end and send data to client end while a number of clients are online.

With Thanks

reply

mahdi87_gh
04/05/2011 - 02:25

Hi all my friends
thanks for this good article.
i want to send a dataTable object through tcp/ip from client To server. by this article ,now i can send text from client to server, but i don't know how to send dataTable?
if i convert dataTable to byte[] and it's size become more than buffer size, my data will split into two or more packets. how should i merge them on the server?
please help.
thanks

reply

Chris
04/05/2011 - 08:34

/// <summary>
/// Great tutorial
/// </summary>
/// <returns>Extra time for a cold beer.</returns>
public bigInt Thanks();

reply

Barter
04/27/2011 - 16:54

Hi,

The tutorial was great and very helpful, but I'm making a server system for some kind of group chat thing, but I have no idea how I can have the client-side application listen for messages getting recieved from the server.

reply

Anonymous
04/29/2011 - 18:02

Hi,

OK I'm sure this tutorial is great but I can't get it to work. I've been searching online for 90 minutes and I can't find a simple WORKING program that I can simply cut and paste into Visual C#2010 and get to work.

Can you please make a simple program that on button1 click runs the server code, button 2 click runs the client code, and button3 sends text from client to server. That way one simple program does it all. I'm going nuts that I cant find a working example that does that. (well i found one that is a console application).

Thanks.

reply

Anonymous
04/30/2011 - 16:03

button 1: server

private void btnServerCreate_Click(object sender, EventArgs e)
{
if (TCP_Server == null)
{
TCP_Server = new Server();

// Ereignishandler aufrufen wenn eine Message empfangen wird
TCP_Server.MessageReceived += new Server.MessageReceivedHandler(Message_Received);

btnServerCreate.Enabled = false;
}
}

button 2: client

private void btnClientSend_Click(object sender, EventArgs e)
{
TcpClient client = new TcpClient();

//IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.105"), 3000);

client.Connect(serverEndPoint);

NetworkStream clientStream = client.GetStream();

ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!\r\n");

clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}

reply

Anonymous
05/02/2011 - 17:20

Hello,

This approach creates one thread per client. I am curious if this is the way to go. I'm been trying to find articles on recommendations to the max number of tasks.

If I had 100 users logged on at once, hence 100 threads, is this ok or will I hit performance issues.

reply

The Reddest
05/03/2011 - 08:22

The number of threads is unlikely to be a performance concern. It depends on what your server is doing, but a basic chat server could probably handle thousands of clients.

reply

Aaron
05/05/2011 - 06:42

I'm having a peculiar problem where clients can connect, but are sometimes automatically disconnected. This happens on/off with periods ranging from minutes to hours in which clients are automatically disconnected right after they connect.

I've left the original code exactly the same, and have only added some Console.WriteLine calls to elaborate. This is what the console reads:

---
Client connected at 5-5-2011
Client disconnected
---

The connection also does NOT show up in netstat after this happens.

I'm using a flash application running from a webserver on the same device to connect to the server. The flash code to connect looks like this:

xmlsock = new Socket();
                               
xmlsock.addEventListener(ProgressEvent.SOCKET_DATA, serverData);
xmlsock.addEventListener(Event.CLOSE, connectionLost );
xmlsock.addEventListener(IOErrorEvent.IO_ERROR, ioError );
xmlsock.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError );
                                xmlsock.connect("SERVER_IP", 3000); //omitted the actual ip, for obvious reasons

What's mostly eating me about this, is that it appears to be completely random. I've found no consistent failure/success, not with browser types, specific computers, IP's, OS's, etc. They all fail/succeed periodically.

reply

Aaron
05/05/2011 - 06:44

Failed to note one thing: there is also no socket error on the server-side. It simply breaks out of the while loop due to bytesRead being 0.

It makes me wonder if there is anything about the actionscript side of this that might be causing such instability, like the Read call returning early and having read nothing.

reply

Aaron
05/05/2011 - 07:06

Also confirmed through a remote desktop connection to the server, that the problem only happens when trying to connect from outside of the server's network.

Upon logging onto the server, I opened a web browser, went to the website address that is pointing to the webserver's IP, and attempted a login. This worked fine.

Tried the same thing from my own PC, got disconnected right away. What could be causing these disconnects, if not the software itself? All my firewalls are open, and I have a public IP address on the server (which connects directly to the ISP, ergo there is no router)

reply

Aaron
05/11/2011 - 09:42

I found a workaround for my problem.

It turns out there was something about the circumstances of the initial connection attempt that caused the connection to destabilize. I implemented a once-a-second ping message from the client, and if it didn't receive a pong within a few seconds it would disconnect and try to reconnect to the server.

Subsequent connections are stable for some reasons. I'm still unclear as to why the initial connection is predominantly severed, but it could have something to do with the fact that it's done almost immediately after the SWF starts running.

reply

stes
05/09/2011 - 10:09

Thanks a lot for this tutorial!
In order to get started with the issue, I searched for a quick and plain tutorial. Well, let's say I was not disappointed!

reply

Hari
05/27/2011 - 17:29

Hi,

How do i test this with client sending data and server returning back?

I am using Visual studio 2010 and i created a console application for server. Then , i created another console application for the client inside the same solution . And when i run the solution, nothing happens. Am i missing something ?

reply

eyal82
06/01/2011 - 10:06

Hey Brandon,

I have a problem figuring out how to send a message from client to client through the server with threads.
For example suppose i have two clients(A and B) connected to the server, and i want to send a message from client A to client B.

So at this moment in the server i have two threads(T1 and T2) for the two clients and the two threads are blocking at read().
Now im doing this:
1. Client A sending a message to the server (with data and client B id).
2. The server recieve the message in thread T1(client A thread).
3. The server gets client B id from the message.
4. The server finds client B from the clients collection, and gets his NetworkStream.
5. The server sends the message using this Stream with write().
6. The server goes back to read() in this thread(T1).

The questions are:
1. Is it ok that all of this was made in thread T1? I mean is it ok that im also communicate with client B through thread T1? or should i somehow tell
thread T2(client B thread) to send the message to client B?
2. Is it a problem that client B networkStream is used in thread T2(blocking with read()) and also in thread T1(with write())?

I really would appreciate if you could help, thanks!
Eyal

reply

The Reddest
06/01/2011 - 11:42

The threads in the server should primarily be used to read from the clients. They should rarely be interrupted for other tasks.

1. Since communicating with client B could take up to 30 seconds (or whatever your timeout is), I would not recommend using T1 to send the information. You'd be blocking yourself from reading any communications from client A while you're attempting to transmit to B. I would recommend having another 'transmit' thread for each client and a queue where messages to transmit could be added. T1 would receive a message, get client B's queue, add the message, and the return to reading. client B's transmit thread would continually be pulling messages out of the queue and sending them.

2. The NetworkStream object can be read and written simultaneously from different threads. I don't think multiple threads can safely write to it simultaneously, so whenever you're using it for writing, just surround it with a lock.

reply

eyal82
06/02/2011 - 00:38

thank you for the fast reply, ok so for each client i will have a "read" thread and a "transmit" thread.

1. Do you recommend to maybe add another thread for each client that would acutualy do the work? i mean after the "read" thread gets the message it adds it to a "jobs" queue, the "doWork" thread would continually be pulling messages out of this queue, do the actual work according to the protocol and prepare a resultMessage, then adds the resultMessage to the destination client "messageToTrensmite" queue that the "transmit" thread will send to the client?

2. When you say "the transmit thread would continually be pulling messages out of the queue" you mean that it continually keep chacking if the queue is not empty?
something like:

while(true)
{
   if(!queue.isEmpty)
   {
   //handel message
   }
}

or maybe its better if some event will trigger it to check the queue?

reply

The Reddest
06/02/2011 - 08:20

1. I don't think another thread would be necessary for handling the message - unless the contents of doWork could take a while and begin blocking the read thread. If all you're doing is parsing the protocol and building a simple response, I think the read thread can do that.

2. Polling the queue would be fine and probably the simplest approach (I'd stick a sleep in there somewhere though). Here's an article talking about a blocking queue, which would essentially block the thread until something was enqueued - this is probably the most correct solution, but is more difficult to implement.

reply

Pool Eng
06/20/2011 - 22:43

Hello Reddest:
I come From ROC(Taiwan).
This is a good example better than MSDN. It's quite simple and clean,thanks for this Tutorial

reply

shafyxl
06/28/2011 - 11:49

Beginners!! better to see the MSDN example fist http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=VS.90).aspx.

reply

Louhike
07/05/2011 - 08:10

Great example !
The code is well written and simple and we easily understand everything just by looking at the code.
Thanks a lot, it's really helpful.

reply

Mouayad AL ZEIN
07/06/2011 - 03:09

First of all, thanks a lot for your article, it helped me a lot in understanding the whole concept.

I have one question :

Let's suppose I want to build a Server class and a Client class using what you have written in your article, I still can't figure out how to make a Client class so that each time I create a client object I can connect it to the Server ?

Your code shows pretty well how to define a server that listens to clients, but how do I launch the clients ?

my question might seem stupid to you, but I'm new to networking and I need an answer badly.

Best Regards

reply

The Reddest
07/06/2011 - 08:35

Here's the shell of a possible client class that may help you out a little.

public class Client : IDisposable
{
   TcpClient _tcpClient;

   // Connects the client to a server at the specified
   // IP address and port.
   public void Connect(IPAddress address, int port)
   {
      _tcpClient = new TcpClient();

      IPEndPoint serverEndPoint =
         new IPEndPoint(address, port);

      _tcpClient.Connect(serverEndPoint);

      // Create a thread to read data sent from the server.
      ThreadPool.QueueUserWorkItem(
         delegate
         {
            Read();
         });
   }

   // Sends bytes to the server.
   public void Send(byte[] buffer)
   {
      _tcpClient.GetStream().Write(
         buffer, 0, buffer.Length);

      _tcpClient.GetStream().Flush();
   }

   private void Read()
   {
      byte[] buffer = new byte[4096];
      int bytesRead = 0;
      while (true)
      {
         bytesRead =
            _tcpClient.GetStream().Read(buffer, 0, 4096);

         // TODO: do something with these bytes
      }
   }

   public void Dispose()
   {
      _tcpClient.Close();
   }
}

reply

rakesh
07/17/2011 - 03:51

thank u so much for this post.. this really helped me a loooot......

reply

remlap21
07/25/2011 - 08:48

Excellent article thank you so much!

reply

Anonymous
07/29/2011 - 07:42

HI
first sry my english.

This is a good example but my client has had several requests.when the server responded with GetBytes() how I jump to the next client request?getstring()

reply

Anonymous
07/29/2011 - 08:45

i mean this:

-client send to server
-server answer and wait for next request and answer
etc.

reply

Anonymous
08/06/2011 - 21:22

I used your code and my Console just sits there and does nothing...

reply

Anonymous
08/06/2011 - 21:30

Never mind

reply

Yehonatan
08/09/2011 - 02:11

Hi,im starting to learn c# again and i wanted to ask something.
On the article above you gave us the directions to create TCP server but what if i want to create TCP client? where can i learn how to create one and not just to copy and paste code?
Thanks.

BTW - your captcha is easy to break if someone using php.

reply

Anonymous
08/16/2011 - 00:12

Iam getting following error at this.tcpListener.Start();

system.collections.listdictionaryinternal An attempt was made to access a socket in a way forbidden by its access permissions..

Please can any one help..

reply

Anonymous
08/27/2011 - 04:28

hi, im starting to learn on c# client server socket programming.
sorry a dumb question..
is your code a multithreaded server socket programming? a server connect by many clients?

thank you.

reply

Anonymous
09/07/2011 - 15:20

Sorry for being a newb but how do I treat every client if I want to send something to them?

reply

antonio
09/12/2011 - 16:45

Hello

First of all thanks for the tutorial it was really helpful to understand tcp.

I'm working in a monitoring application based in a Modbus TCP IP communication model, the client has a timmer that sends one command to read the registers in the remote server, and the server recives the command and sends back the information, the fact is that I dont know if I should use synchronous or asynchronous calls.

thanks

reply


09/16/2011 - 06:01

Nice explanation, thanks....!!

reply

ch0eb1t
09/19/2011 - 12:42

allright, I found a very bad problem.
when I close the program by clicking the x button on the top right corner of the winform, after starting the thread of course.
The listener is still running and you can see it with the task manager.
if you use the build mode, the IDE won't exit from the build mode except when you stop it.
or if you're using (ctrl+F5), do it again, and it will give you an error.

This problem's so bad.
even though the thread and program is closed, the
this.tcpListener.AcceptTcpClient();
line is still running.

reply

The Reddest
09/19/2011 - 14:02

Yep, the code here is not feature complete, just a shell. When the app closes, just call Stop on the TcpListener.

reply

ch0eb1t
09/19/2011 - 20:52

I'm sorry, but can you please tell me where to put the tcplistener.stop whenever I close the program? :)
the server code is written in different class from the main winform app. The server thread is created when I clicked a "Start" button.
I'm trying to solve this problem but I'm getting a dead end.

reply

The Reddest
09/20/2011 - 07:55

The server class should expose some way to start and stop it.

public class Server
{
  public void Start()
  {
    // Called by the application when the
    // start button is pressed.
  }

  public void Stop()
  {
    // Called by the application when it
    // it closed.
  }
}

reply

ch0eb1t
09/21/2011 - 09:51

thank you for your help :)
now the problem's fixed.
I'm sending an empty packet to the tcp server right before the app closed so it will release the thread from listening to tcp packet. :)

reply

anonhj
09/21/2011 - 00:41

thanks for the code

i have error in this:

client.Connect(serverEndPoint);

i dont know how to solve it, can help me on it.

thanks again.

reply

ch0eb1t
09/21/2011 - 09:54

does the client code run on different machine?

reply

anonhj
09/21/2011 - 23:53

yes, i try to run it on different machine and also run on same machine. For now, the error was solved, but, both client and server seem not connect to each other, i post my code down there, if possible please check for me. thanks a lot.

reply

ch0eb1t
09/23/2011 - 22:56

change the 127.0.0.1 on the client program
to your server PC IP address

reply

anonhj
09/26/2011 - 08:20

yup, i change already, but still no response from both client and server. i really have no idea about it. :(

reply

BlueButtons
09/21/2011 - 21:25

Hello, i was wondering, how do you connect to computers that have a different IP address. For instance, if i want to run your client and server seperately on two different machines, loopback (or using the localhost) won't allow for this....

Not too familiar with networking, any help would be greatly appreciated!

reply

ch0eb1t
09/23/2011 - 22:44

The two computers must be on the same LAN

consider it:
Computer A IP address : 192.168.0.5 running the server code
Computer B IP address : 192.168.0.6 running the client code

in Computer B, change:

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

with

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.0.6"), 3000);

reply

anonhj
09/21/2011 - 23:47

hi, i had been trying out the code, no error, but dont know why both client and server are not connect to each other, nothing response, something wrong in my code, please help me, thanks a lot.

server code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net; //networking
using System.Net.Sockets; //networking
using System.Threading; //networking
using System.Net.NetworkInformation; //monitor bandwidth


namespace NBCS_serverlogin
{
    public partial class NBCSadmin : Form
    {
        private TcpListener tcpListener;
        private Thread threadTcp;
        static NetworkStream clientStream;
        const int portnumber = 3333;

        //public delegate void ChangedEventHandler(object sender, EventArgs e);
        // public event ChangedEventHandler Changed;

        public NBCSadmin()
        {
            InitializeComponent();
            portnotxt.Text = "3333";
            // initiateListen();
        }

        private void initiateListen()
        {
            //Tcp
            this.tcpListener = new TcpListener(IPAddress.Any, portnumber);
            tcpListener.Start();
            int intPort = Convert.ToInt32(portnotxt.Text.Trim());
            this.threadTcp = new Thread(new ThreadStart(ListenToClients));
           
            //for(int z=0; z<3; z++)
        }

        //listen for connected client
        private void ListenToClients()
        {
            //tcpListener.Start();

            while (true)
            {
                try
                {
                    // block till client connect to server
                    TcpClient clientCom = this.tcpListener.AcceptTcpClient();

                    //handle connected clients
                    Thread threadClient = new Thread(new ParameterizedThreadStart(HandleClients));
                    threadClient.Start(clientCom);
                    constatuslabel.Text = "Received Client Connection.";

                }
                catch (SocketException)
                {
                    MessageBox.Show ("error");
                }
            }
        }
        private void HandleClients(object clientCom)
        {
            TcpClient tcpClient = (TcpClient)clientCom;
            clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    bytesRead = clientStream.Read(message, 0, 4096);
                }

                catch (Exception)
                {
                    // error happened
                    break;
                }

                if (bytesRead == 0)
                {
                    // client diconnected to server
                    constatuslabel.Text = "Client has disconnected from the server.";
                    break;
                }

                //msg has been successfully received
                ASCIIEncoding asciiEncoder = new ASCIIEncoding();
                // output msg
                constatuslabel.Text = tcpClient.Client.LocalEndPoint + "" + tcpClient.Client.RemoteEndPoint + asciiEncoder.GetString(message, 0, bytesRead);

                //System.Diagnostics.Debug.WriteLine(asciiEncoder.GetString(message, 0, bytesRead));
            }
            // (button)
            tcpClient.Close();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            //MessageBox.Show("Logout Successful, Thank you.");  

            //serverlogin Serverlogin = new serverlogin();
            //this.Hide(); this.Close(); < close the current form
            //Serverlogin.Show();
        }


        private void connecttoclientbtn_Click_1(object sender, EventArgs e)
        {
            initiateListen();
            constatuslabel.Text = "Waiting for a connection...";
           
        }

        private void label13_Click(object sender, EventArgs e)
        {
            //Add event to handle when client is connected
            //Changed += new ChangedEventHandler(ClientAdded);
            //TreeNode node;

            //constatuslabel = new Label();
        }

        private void stopconnbtn_Click(object sender, EventArgs e)
        {
            tcpListener.Stop();
            constatuslabel.Text = "Connection disconnected...";
        }

    }
}

client code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace NBCS_Client
{
    public partial class NBCSuser : Form
    {
        static TcpClient clientuser;
        IPEndPoint serverEndPoint;
        NetworkStream clientStream;
        const int portnumber = 3333;
        string myIPAdd = string.Empty;
        string strgAddress = string.Empty;

        public NBCSuser()
        {
            //InitializeComponent();

            InitializeComponent();
            ipaddtxt.Text = "127.0.0.1";
            portnotxt.Text = "3333";
        }

        public void initiateListenUser()
        {
            clientuser = new TcpClient();

            //get the remote ip add
            IPAddress ipaddress = IPAddress.Parse(ipaddtxt.Text.Trim());
            int intPort = System.Convert.ToInt32(portnotxt.Text.Trim());
            //create end point
            serverEndPoint = new IPEndPoint(ipaddress, portnumber);

        }

        public void connectTcpServer()
        {
            clientuser.Connect(serverEndPoint);
            clientStream = clientuser.GetStream();

            //create thread to handle communication with connected client
            Thread threadClient = new Thread(new ParameterizedThreadStart(HandleClients));
            threadClient.Start(clientuser);

        }

        public void HandleClients(object clientuser)
        {
            TcpClient tcpclient = (TcpClient)clientuser;
            NetworkStream clientStream = tcpclient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    //block until client send a msg
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch (SocketException)
                {
                    //socket error
                    break;
                }

                if (bytesRead == 0)
                {
                    //client disconnected to server
                    break;
                }
                //msg received successfully
                ASCIIEncoding asciiEncoder = new ASCIIEncoding();
                // output msg
                userconstatuslabel.Text = tcpclient.Client.LocalEndPoint + "" + tcpclient.Client.RemoteEndPoint + asciiEncoder.GetString(message, 0, bytesRead);
                //textFrmServer

            }
            tcpclient.Close();

        }

        private void connectserverbtn_Click(object sender, EventArgs e)
        {
            initiateListenUser();
            connectTcpServer();
            userconstatuslabel.Text = "Connecting to server...";
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void exitbtn_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}

reply

umm
09/23/2011 - 09:11

After i have used the send method from server, how do i open that message on client?

reply

Mikki
09/24/2011 - 09:54

What do you mean by the word "block?" That it stops waiting for clients until one has connected?

reply

The Reddest
09/26/2011 - 08:31

In this case, block means execution will not continue until a client connects or an error occurs.

reply

BAJA
10/07/2011 - 13:25

someone can put a link whit a functioning code, because i am nuub and y dont undertant so well

reply

eyal82
10/10/2011 - 13:35

Hey Brandon,

I know this is a bit out of scope but can you show how to add SSL support if its not too complicated?

reply

hossam
10/16/2011 - 12:14

NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
 

I got an error in the last two lines

reply

antonio
10/18/2011 - 15:08

Hello

I'm new in C++ and I'm working on the client code but I always get the same
error C3364: 'System::Threading::ParameterizedThreadStart' : invalid argument for delegate constructor; delegate target needs to be a pointer to a member function

I also tried with ThreadPool::QueueUserWorkItem(delegate Read_Multipl_Reg(direccion, unidad, referencia,cantidad,registros));

but it doesn't work either

can someone help me to see how to solve it

thanks

#pragma once
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <ios>
using std::cout;
using std::cin;
using namespace System;
using namespace System::Text;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Threading;


public ref class cliente
{
        TcpClient^ ClienteMBTCP;
        Thread^ hilocliente;
        int cantidad;
        int unidad;
        int referencia;
        String^ direccion;
        array<byte>^ registros;
public:
        cliente(){
                        }
public:
       
        void Connect(String^ address, int port)
   {
      ClienteMBTCP = gcnew TcpClient();
      ClienteMBTCP->Connect(address, port);
      // Create a thread to read data sent from the server.
      //ThreadPool::QueueUserWorkItem(delegate Read_Multipl_Reg(direccion, unidad, referencia,cantidad,registros));
          cliente^ mb=gcnew cliente();
          hilocliente = gcnew Thread(gcnew ParameterizedThreadStart(mb,cliente::Read_Multipl_Reg(direccion, unidad, referencia,cantidad,registros) ) ); //error line
          hilocliente->Start(ClienteMBTCP);
        }
       
        void Send(array<byte>^ buffer)
   {
      ClienteMBTCP->GetStream()->Write(buffer, 0, buffer->Length);
      ClienteMBTCP->GetStream()->Flush();
   }
       
        void Read_Multipl_Reg (String^ dns,  int unidad,int referencia, int cantidad, array<byte>^ registros )
        {
         int i;
         array<byte>^ buffer = gcnew array<byte>(256);
       
                 for ( i=0; i<5; i++ )
                         buffer[ i ] = 0;
                 buffer[ 6 ] = (byte) unidad;
                 buffer[ 7 ] = 3;
                 buffer[ 8 ] = (byte) (referencia >> 8);
                 buffer[ 9 ] = (byte) (referencia & 0xFF);
                 buffer[ 10 ] = 0;
                 buffer[ 11 ] = (byte) cantidad;
                 buffer[ 5 ] = 6;
                 for(int e=0;e<buffer->Length;e++)
                                 cout<<buffer[e]<<"es el valor";

//Enviar la solicitud al servidor
          Send(buffer);
// Esperar y leer la respuesta
        Read();
        }


void cliente:: Read()
   {  
      array<byte>^ buffer = gcnew array<byte>(256);
      int bytesRecibidos = 0;
      while (true)
      {
         try{
                  bytesRecibidos = ClienteMBTCP->GetStream()->Read(buffer, 0, 256);
                 }catch (Exception^ e)
                {
                    // error happened
                    break;
                }
                 // Verificar la respuesta y extraer los valores leídos
                 if ( bytesRecibidos == ( 9+2*cantidad ) && buffer[ 7 ] == 3 )
                 {
                         array<byte>^ registros = gcnew array<byte>(256);
                         for ( int i = 0; i<cantidad; i++ )
                         {
                        // Construir el valor de registro de los bytes alto y bajo
                                 registros[ i ] = ( ( (byte) buffer[ 10+2*i ] ) << 8 ) & 0xFF00 | ( (byte) buffer[ 11+2*i] & 0xFF );
                                 cout << "El valor del registros[i]= "<< registros[i];
                         }
                 }
                 else
                        cout<< "respuesta erronea";
                               
   }
   }

};

reply

scriptinphp
11/10/2011 - 10:22

Great Tutorial.

question though, kinda of off topic, but here goes:

I am in need of a traceroute application, and have found source for one, but I have tried changing it to use TCP (with my extremely limited knowledge). Is there any way you could help with conversion to work with TCP vs UDP?

http://dice.neko-san.net/2011/01/my-traceroute-for-windows/

you can respond to me at ^^ gmail.com

reply

Anonymous
12/07/2011 - 09:36

hi,

first of all, nice tutorial!

im new to client/server programming. but i was wondering if you could help me with a project im working on.

i'm trying to send a video file from client to server which is 20 megs big.

my question is, what do i need to change in the code to be able to stream video?

and how do i split the bytes instead of sending it all at once?

thanks in advance!

reply

Anonymous
12/14/2011 - 08:11

hi,i have to write a multithreaded connection oriented server using C/C++ and gcc.the server should be able to handle multiple clients concurrently and simulate it for a minimum of ten concurrent clients

reply

Anonymous
12/16/2011 - 17:36

Awesome walk-through. This is the simplest explanation of C# Tcp that I have read. Very nicely done!

reply

maryam
12/24/2011 - 09:06

thank you.

best regard for all friend

reply

Anonymous
12/26/2011 - 10:59

hi every one,
i have designed an instant news sending application for our customers.(using c# socket and async methods.)
The server accepts the connection and keeps them in a list as connected users. When a news is entered to database, the server program sends the news to the connected users. In here, the client should stay connected whole day to recieve the news when added.
I want to ask is there any time limitation for the connection to be alive. If 3 hours no news entered, then are the connections still alive and ready to recieve ?
I am not asking to reconnect when disconnect conditions occurs. I have implemented those exceptional scenarios to reconnect.
I searched too much but i could not find the answer i am looking for.

reply

Mike Hometchko
01/08/2012 - 01:31

For those of you who are looking for a simple two-way communication resolution (and I've seen a ton of posts requesting it) I'll post my code here.

Server

    public class Server
    {
        private TcpListener tcpListener;
        private Thread listenThread;

        public Server()
        {
            this.tcpListener = new TcpListener(IPAddress.Any, 3000);
            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));
                Thread clientThreadSend = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
                clientThreadSend.Start(client);
            }
        }
        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            TcpClient sendClient = (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));

                Console.WriteLine("To: " + tcpClient.Client.LocalEndPoint);
                Console.WriteLine("From: " + tcpClient.Client.RemoteEndPoint);
                Console.WriteLine(encoder.GetString(message, 0, bytesRead));
                clientStream.Flush();
                sendToClient("Test back", sendClient);
            }

            tcpClient.Close();
        }
        public void sendToClient(String line, TcpClient client)
        {
            try
            {
                NetworkStream stream = client.GetStream();
                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] buffer = encoder.GetBytes(line + "\0");

                stream.Write(buffer, 0, buffer.Length);
                stream.Flush();
            }
            catch
            {
                Console.WriteLine("Client Disconnected."+Environment.NewLine);

            }
        }

        public void broadcast(String line, TcpClient thisClient)
        {
            sendToClient(line, thisClient);
        }
    }

Client

    public class Client
    {
        TcpClient _tcpClient;

        // Connects the client to a server at the specified
        // IP address and port.
        public void Connect(IPAddress address, int port)
        {
            _tcpClient = new TcpClient();

            IPEndPoint serverEndPoint =
               new IPEndPoint(address, port);

            _tcpClient.Connect(serverEndPoint);

            // Create a thread to read data sent from the server.
            ThreadPool.QueueUserWorkItem(
               delegate
               {
                   Read();
               });
        }

        // Sends bytes to the server.
        public void Send(byte[] buffer)
        {
            _tcpClient.GetStream().Write(
               buffer, 0, buffer.Length);

            _tcpClient.GetStream().Flush();
        }

        private void Read()
        {
            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] buffer = new byte[4096];
            int bytesRead;
            while (true)
            {
                bytesRead =
                   _tcpClient.GetStream().Read(buffer, 0, 4096);
                Console.WriteLine(encoder.GetString(buffer, 0, bytesRead));
            }
        }        

        public void Dispose()
        {
            _tcpClient.Close();
        }
    }

Hope this helps!

reply

nikos
01/11/2012 - 15:27

hello, im new in Promela and i have to simulate the TCP/IP connection management with flow control in Promela and i need help. thnx.

reply

Piyush Dixit
01/12/2012 - 06:58

Hi,
Thx for the code it is working great.

my problem is when i try to invoke tcp server Application from my wcf service.
i get the exception..

please help..

reply

Anonymous
01/13/2012 - 07:02

Quote of the day:

'although in practice this is limited because you can only spawn so many threads before Windows will get upset'

Brilliantly put, Windows got upset with me recently as well.

reply

MindHACKer
01/23/2012 - 17:20

This was very helpful, THANK YOU VERY MUCH.

reply

Anonymous
01/25/2012 - 05:22

Rectangle rect= new Rectangle();
rect.width = 10;
rect.height = 10;
rect.StrokeThickness = 1;
rect.Stroke = Brushes.Black;

Point startPoint= new Point(54, 52);
Canvas.SetLeft(rect,startPoint.X);
Canvas.SetTop(rect,startPoint.X);
canvas.Children.Add(rect);

reply

Anonymous
01/25/2012 - 05:48

Dispatcher.Invoke(new Action(() =>
                    {
                        canvas.Children.Add(rect);
                    }));

reply

Dilip Sharma
02/10/2012 - 03:03

Help Full

Thanks For Post

reply

Anonymous
02/11/2012 - 10:54

My program gives an error with the TcpClient.GetStream() command. It doesn't recognize this function. Am I missing a declaration somewhere?

reply

Anonymous
02/11/2012 - 10:57

Nevermind, found the problem - I had the t in tcpClient capitalized.

reply

GAWRRELL
02/13/2012 - 05:20

Hy, i have tested the tutorial and i get an error

A first chance exception of t
type 'System.Threading.WaitHandleCannotBeOpenedException' occurred in mscorlib.dll

Additional information: No handle of the given name exists.

Can anyone tell me how to fix this ?

reply

The Reddest
02/13/2012 - 14:13

What line of code throws the exception?

reply

Anonymous
02/15/2012 - 01:29

I used u r code but,

When I send some msgs from the client to server, i got an error
" The calling thread cannot access this object because a different thread owns it."
on this line

" ASCIIEncoding encoder = new ASCIIEncoding();
txtContent.Textencoder.GetString(message, 0, bytesRead);"

help me.........

Am a beginner to the Socket pgming........

reply

Anonymous
02/17/2012 - 08:06

Thank you for the detailed and simple explanation. This is what I needed.

reply

Anonymous
02/18/2012 - 16:28

First..thank you for the post!
I am working with the DataMax printer that is connected directly to the PC via network card. I have a TCP client tester that can send DPL commands to the printer and this part works well. However, I would like to add a Listner to get printer response. For example, when I send a command I should get back 3 blocks of eight bits each. My tester gets this reply but sometimes I need to send twice my command to get it. I think the listner that you are using would take care of it, but I am not sure how to use it in my app. My app is a simple windows form with one button, and response txt box.

Here is the link to the code I used in my app:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx

I made small changes to it as my app shows a form:

        void SendCommandToNetworkPrinter(String server, String message)
        {
            try
            {
           
                // Create a TcpClient.
                // Note, for this client to work you need to have a TcpServer
                // connected to the same address as specified by the server, port
                // combination.
                Int32 port = System.Convert.ToInt32(txtPortId.Text);
                TcpClient client = new TcpClient(server, port);

                // Translate the passed message into ASCII and store it as a Byte array.
                Byte[] data = Encoding.ASCII.GetBytes(message);//System.Text.Encoding.ASCII.GetBytes(message);

                // Get a client stream for reading and writing.
                Stream stream = client.GetStream();

                //NetworkStream stream = client.GetStream();

                // Send the message to the connected TcpServer.
                stream.Write(data, 0, data.Length);

                stream.Flush();

                //Console.WriteLine("Sent: {0}", message);
                //MessageBox.Show("Sent:" + message);
                txtReply.Text += "SENT:" + message;

                // Receive the TcpServer.response.

                // Buffer to store the response bytes.
                data = new Byte[256];

                // String to store the response ASCII representation.
                String responseData = String.Empty;

                // Read the first batch of the TcpServer response bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                //Console.WriteLine("Received: {0}", responseData);
                    //txtReply.Text += "  RECEIVED: " + responseData;
                //lboxIds.Text += "Received: " + responseData;
                txtListen.Text = responseData;

               

                // Close everything.
                stream.Close();
                client.Close();
            }
            catch (ArgumentNullException e)
            {
                //Console.WriteLine("ArgumentNullException: {0}", e);
                MessageBox.Show("ArgumentNullException:" + e.Message + e.StackTrace);
            }
            catch (SocketException e)
            {
                //Console.WriteLine("SocketException: {0}", e);
                MessageBox.Show("SocketException:" + e.Message + e.StackTrace);
            }

            //Console.WriteLine("\n Press Enter to continue...");
            //Console.Read();
        }

reply

Anonymous
03/30/2012 - 04:55

Please note that NetworkStream.Flush() has no effect on the data in the stream.

http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.flush.aspx

reply

LuisF
04/02/2012 - 14:02

Hi that´s a great explanation and a great code thank you very much.
I have a question: How to get the IP address of the connected client?, I have looked to the tcpClient members but couldn't find any related option there and don´t know where could i get it

Thank a bunch!

reply

LuisF
04/02/2012 - 14:06

Ohh men, I´m not native English speaker, I have always thought that "Thanks a bunch" was thanks a lot, I just searched for for curiosity and found it was sarcastic sorry men, you know i meant thanks a lot!

reply

Danish Coder
04/03/2012 - 04:54

My new best friend ;-)
Thx m8

reply

Gio
05/03/2012 - 19:15

Very good essential example !

Thanks a lot !

reply

Anonymous
05/08/2012 - 19:12

Hello,
Me I am having problem to handle an exception at the line
NetworkStream clientStream = tcpClient.GetStream();

A NullPointerException..

I try to catch it by doing this:
try{
NetworkStream clientStream = tcpClient.GetStream();
}catch
{
Console.WriteLine("An error /...");
}
I can catch the exception but my program can not continue. it breaks at this level.
How can I solve it??

reply

Dias
05/09/2012 - 09:31

Very good post

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.