C# Tutorial - Simple Threaded TCP Server

简介: <p style="margin-top:0px; margin-bottom:18px; font-family:museo-sans,'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:16px; line-height:24px; color:rgb(74,74,74)"> In this tutorial I'm goin

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 functionListenForClients 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 theNetworkStream 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.

http://tech.pro/tutorial/704/csharp-tutorial-simple-threaded-tcp-server

相关文章
|
1月前
|
开发框架 缓存 .NET
C# 一分钟浅谈:Blazor Server 端开发
Blazor Server 是基于 ASP.NET Core 的框架,允许使用 C# 和 Razor 语法构建交互式 Web 应用。本文介绍 Blazor Server 的基本概念、快速入门、常见问题及解决方案,帮助开发者快速上手。涵盖创建应用、基本组件、数据绑定、状态管理、跨组件通信、错误处理和性能优化等内容。
40 1
|
1月前
|
缓存 C# 开发者
C# 一分钟浅谈:Blazor Server 端开发
本文介绍了 Blazor Server,一种基于 .NET 的 Web 开发模型,允许使用 C# 和 Razor 语法构建交互式 Web 应用。文章从基础概念、创建应用、常见问题及解决方案、易错点及避免方法等方面详细讲解,帮助开发者快速上手并提高开发效率。
50 2
|
2月前
|
网络协议 网络性能优化 C#
C# 一分钟浅谈:UDP 与 TCP 协议区别
【10月更文挑战第8天】在网络编程中,传输层协议的选择对应用程序的性能和可靠性至关重要。本文介绍了 TCP 和 UDP 两种常用协议的基础概念、区别及应用场景,并通过 C# 代码示例详细说明了如何处理常见的问题和易错点。TCP 适用于需要可靠传输和顺序保证的场景,而 UDP 适用于对延迟敏感且可以容忍一定数据丢失的实时应用。
51 1
|
4月前
|
Linux C#
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
|
7月前
|
网络协议 C# C++
BytesIO | C# 超简洁的TCP服务端开发(完整源码+视频教程)
本章将继续利用BytesIO开发TCP的服务端,简洁明了依然是主旋律,我们要在三十行代码内除了实现一个TCP服务端以外,使其支持聊天室(消息转发)、连接数限制、心跳超时检测等功能。 现在,一起跟着视频敲一敲吧!
533 0
BytesIO | C# 超简洁的TCP服务端开发(完整源码+视频教程)
|
7月前
|
网络协议 C# C++
BytesIO | 零基础轻松看懂 C# TCP客户端(完整源码+视频教程)
零基础轻松看懂 C# TCP客户端(完整源码+视频教程) 如果非IT行业的女朋友都能学会的话,应该就算0基础入门的教学视频了吧! 超简单的C# TCP开发入门,短短的代码,完整的功能,掏出你的VS码一个试试手吧!
186 0
BytesIO | 零基础轻松看懂 C# TCP客户端(完整源码+视频教程)
|
7月前
|
网络协议 Unix Linux
【Unity 3D】C#中Socket及TCP三次握手与四次挥手详解(超详细 图文解释)
【Unity 3D】C#中Socket及TCP三次握手与四次挥手详解(超详细 图文解释)
246 0
|
网络协议 C#
C#编程-60:简单的TCP通讯实例
C#编程-60:简单的TCP通讯实例
177 0
C#编程-60:简单的TCP通讯实例
项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端
项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端
项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端