【转载】C# Tutorial - Simple Threaded TCP Server
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的更多相关文章
- Building a Non-blocking TCP server using OTP principles
转自:https://erlangcentral.org/wiki/index.php/Building_a_Non-blocking_TCP_server_using_OTP_principles ...
- [转] 3个学习Socket编程的简单例子:TCP Server/Client, Select
以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序.如果你能完全理解这3个例子,估计 ...
- Socket TCP Server一个端口可以有多少个长连接?受到什么影响?linux最大文件句柄数量总结
Socket TCP Server一个端口可以有多少个长连接? 网上答案很多,不知道那个才是正确的 理论上是无限的 16.Linux中,一个端口能够接受tcp链接数量的理论上限是? A.1024 B. ...
- socket - socketserver - start TCP server
前面提到如何使用socket模块启动tcpserver: 创建socket:sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 绑定ip: ...
- [转]一个基于完成端口的TCP Server Framework,浅析IOCP
[转]一个基于完成端口的TCP Server Framework,浅析IOCP http://www.cppblog.com/adapterofcoms/archive/2010/06/26/1187 ...
- 基于 LWIP 建立 TCP Server 与主机通信实验
LWIP 版本:2.0.3 上一篇文章是写如何将 LWIP 移植到板子上,今天晚上记录基于 LWIP 实现与主机的网络通信. 先是打开了原子的实验例程,大概浏览了一遍,觉得 TCP 网络网络通信也就是 ...
- swoole深入学习 2. tcp Server和tcp Client
这节来学习Swoole最基础的Server和Client.会通过创建一个tcp Server来讲解. server <?php class Server { private $serv; pub ...
- Modbus库开发笔记之九:利用协议栈开发Modbus TCP Server应用
前面我们已经完成了Modbus协议栈的开发,但这不是我们的目的.我们开发它的目的当然是要使用它来解决我们的实际问题.接下来我们就使用刚开发的Modbus协议栈开发一个Modbus TCP Server ...
- Modbus库开发笔记之三:Modbus TCP Server开发
在完成了前面的工作后,我们就可以实现有针对性的应用了,首先我们来实现Modbus TCP的服务器端应用.当然我们不是做具体的应用,而是对Modbus TCP的服务器端应用进行封装以供有需要时调用. 这 ...
随机推荐
- Q_INIT_RESOURCE宏
QT应用程序,无论是exe,staticlib,还是dll程序,都可以通过qrc文件来导入各种资源. qrc会将这些资源文件转换为相应代码,参与应用程序的编译. 这样做的好处就是:简化了应用程序发 ...
- yum 命令提示语法错误
1. 问题信息 SyntaxError: invalid syntax 2. 问题原因 升级python版本导致 3. 解决方法 vi /usr/bin/yum 将#!/usr/bin/python ...
- felx基础知识
felx4将功能组件划分为3个命名空间分别是 fx:核心功能 mx:标准flex3组件组 s:新flex4 spark组件组
- 如何用eclipse搭建Android的开发环境
l开发主要应用Eclipse 3.7版本. l辅助工具为jdk.Androidsdk Android环境搭建 –1.1.JDK安装 –1.2.Eclipse安装 –1.3.Android SDK安 ...
- Think in java浏览一
Think in java作为java语言的圣经书籍之一,几乎成为每个java程序员必看的书籍,不看都不好意思说自己是java程序员,不过一般也不说自己认真看了,就说自己翻了翻.作为写安卓的,当然也要 ...
- Android中使用shape实现EditText圆角
之前看到手机上的百度editText控件是圆角的就尝试做了一下,看了看相关的文章. 因为代码少,看看就知道了.所以下面我就直接贴上代码供大家参考,有其他的好方法记得分享哦~ 整个代码不涉及JAVA代码 ...
- MVC小系列(二十)【给Action提供HttpStatusCodeResult】
主要用到: HttpStatusCodeResult 和HttpStatusCode 的http返回状态 比如: /// <summary> /// 使用异步模式 /// </sum ...
- 使用instsrv.exe+srvany.exe将应用程序安装为windows服务[转]
转自:http://qingmu.blog.51cto.com/4571483/1248649 一.什么是instsrv.exe和srvany.exe instsrv.exe.exe和srvany ...
- AWK详细用法
awk非常的优秀,运行效率高,而且代码简单,对格式化的文本处理能力超强.基本上grep和sed能干的活awk全部都能干,而且干得更好. 先来一个很爽的例子:文件a,统计文件a的第一列中是浮点数的行的浮 ...
- swift 自行理解