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

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.

【转载】C# Tutorial - Simple Threaded TCP Server的更多相关文章

  1. Building a Non-blocking TCP server using OTP principles

    转自:https://erlangcentral.org/wiki/index.php/Building_a_Non-blocking_TCP_server_using_OTP_principles ...

  2. [转] 3个学习Socket编程的简单例子:TCP Server/Client, Select

    以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序.如果你能完全理解这3个例子,估计 ...

  3. Socket TCP Server一个端口可以有多少个长连接?受到什么影响?linux最大文件句柄数量总结

    Socket TCP Server一个端口可以有多少个长连接? 网上答案很多,不知道那个才是正确的 理论上是无限的 16.Linux中,一个端口能够接受tcp链接数量的理论上限是? A.1024 B. ...

  4. socket - socketserver - start TCP server

    前面提到如何使用socket模块启动tcpserver: 创建socket:sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 绑定ip: ...

  5. [转]一个基于完成端口的TCP Server Framework,浅析IOCP

    [转]一个基于完成端口的TCP Server Framework,浅析IOCP http://www.cppblog.com/adapterofcoms/archive/2010/06/26/1187 ...

  6. 基于 LWIP 建立 TCP Server 与主机通信实验

    LWIP 版本:2.0.3 上一篇文章是写如何将 LWIP 移植到板子上,今天晚上记录基于 LWIP 实现与主机的网络通信. 先是打开了原子的实验例程,大概浏览了一遍,觉得 TCP 网络网络通信也就是 ...

  7. swoole深入学习 2. tcp Server和tcp Client

    这节来学习Swoole最基础的Server和Client.会通过创建一个tcp Server来讲解. server <?php class Server { private $serv; pub ...

  8. Modbus库开发笔记之九:利用协议栈开发Modbus TCP Server应用

    前面我们已经完成了Modbus协议栈的开发,但这不是我们的目的.我们开发它的目的当然是要使用它来解决我们的实际问题.接下来我们就使用刚开发的Modbus协议栈开发一个Modbus TCP Server ...

  9. Modbus库开发笔记之三:Modbus TCP Server开发

    在完成了前面的工作后,我们就可以实现有针对性的应用了,首先我们来实现Modbus TCP的服务器端应用.当然我们不是做具体的应用,而是对Modbus TCP的服务器端应用进行封装以供有需要时调用. 这 ...

随机推荐

  1. stoi的例子

    9.51 设计一类,它又三个unsigned成员,分别表示年月日.为其编写构造函数,接受一个表示日期的string参数. 程序如下: #include<iostream> #include ...

  2. 进程控制之更改用户ID和组ID

    在UNIX系统中,特权(例如能改变当前日期的表示法以及访问控制(例如,能否读.写一特定文件))是基于用户ID和组ID的.当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们需要更换自己的用户I ...

  3. C# - 系统类 - DateTime类

    DateTime类 ns:System 此类是一个结构 提供了访问和修改它所代表的时间 创建DateTime实例的几种方式 DateTime time = , , , , , ); Console.W ...

  4. phpcms 源码分析二:

    这次是逆雪寒的common.inc.php第二部分: <?php /* 明天放假了.今天在写点罗.放假没空写了.要陪老婆,大家看了有什么不明白的.可以跟帖问.我懂的我会回答.谢谢 [/php] ...

  5. Foundation: NSNotificationCenter

    一个NSNotificationCenter对象(通知中心)提供了在程序中广播消息的机制,它实质上就是一个通知分发表.这个分发表负责维护为各个通知注册的观察者,并在通知到达时,去查找相应的观察者,将通 ...

  6. Cookie中用户登录信息的提示

    public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpSe ...

  7. Python 基础【第二篇】python操作模式

    一.交互模式 #python Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) [GCC 4.4.7 20120313 (Red Hat 4.4.7-4 ...

  8. Zepto源码解读

    /*******************************************************************************Zepto核心和dom操作******* ...

  9. react环境搭建

    react-webpack文件夹是开发目录,在此目录下执行命令,假设你已经正确安装了 nodejs 一:参照教程搭建环境 https://github.com/newtriks/generator-r ...

  10. Think in java浏览一

    Think in java作为java语言的圣经书籍之一,几乎成为每个java程序员必看的书籍,不看都不好意思说自己是java程序员,不过一般也不说自己认真看了,就说自己翻了翻.作为写安卓的,当然也要 ...