C#里面提供了Socket类,通过该类,可以很轻松地搭建起Socket服务端和客户端。本文将尽量以最简单的方式、最少的代码量来说明一个简易的Socket服务器是怎么搭建起来的。

首先,大概讲下整个思路和流程:

(1)首先要明白一个概念:整个服务器,实际上就是由一个Socket对象监听端口;

(2)我们会通过一个新的线程监听客户端发起连接请求,这样的好处是避免堵塞主线程;

(3)当与客户端建立起连接之后,我们还会新建线程来专门接受该socket客户端的数据。

先新建各类:
public class SocketServer { }
定义一些属性变量:
//端口号 private int SocketServerPort = 5002; //处理连接请求的线程 private Thread
acceptConnectReqThd;
然后写一个服务器启动的函数Start
/// <summary> /// 启动服务器 /// </summary> public bool Start() { try {
//创建一个socket对象 Socket socketWatch = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp); //获取IP IPAddress ip = IPAddress.Any;
//创建端口号 IPEndPoint port = new IPEndPoint(ip, SocketServerPort); //监听
socketWatch.Bind(port); Console.WriteLine("监听成功"); socketWatch.Listen(20);
//设定最大的挂起长度 //新建线程来处理连接请求 acceptConnectReqThd = new
Thread(AcceptConnectReqHandler); acceptConnectReqThd.IsBackground = true;
acceptConnectReqThd.Start(socketWatch); //把socket对象当做参数传递给到线程里面的方法 return true;
} catch(Exception e) { return false; } }
执行Start函数之后,我们就创建了一个socket对象,并监听我们设定的端口号5002。并添加了个线程来处理客户端的连接请求。

接下来我们实现AcceptConnectReqHandler方法,即线程驱动的方法:
/// <summary> /// 连接请求的处理函数 /// </summary> /// <param name="_socket"></param>
private void AcceptConnectReqHandler(object _socket) { try { //服务端的socket对象
Socket serverSocket = (Socket)_socket; while (true) {
//获取客户端socket。Accept方法处理任何传入的连接请求,并返回可用于与远程主机通信数据的Socket对象,即客户端的socket。
//这一句话会卡主线程。只要没有新的链接进来,就会一直卡主不动(等待中)。 //收到连接事件后,会往下执行,通过while又回到这里继续等待 Socket
clientSocket = serverSocket.Accept(); //创建接受客户端消息的线程 Thread acceptMsgReqThd =
new Thread(ReciveMsgReqHandler); acceptMsgReqThd.IsBackground = true;
acceptMsgReqThd.Start(clientSocket); } } catch (Exception e) {
Console.WriteLine("服务端处理连接事件异常:" + e.ToString()); } }
这个线程驱动的函数里面,只要收到一个客户端的请求链接,就会再新建一个线程来收数据。有N个客户端链接,就会添加N个线程。

现在我们来实现收数据的方法ReciveMsgReqHandler
/// <summary> /// 接收客户端socket消息 /// </summary> /// <param
name="_socket"></param> private void ReciveMsgReqHandler(object _socket) {
Socket clientSocket = (Socket)_socket; try { while(true) {
//客户端连接成功后,接受来自客户端的消息 if (clientSocket == null) { continue; } byte[] buffer =
new byte[MAX_SEND_FILE_LENGTH]; //数据缓冲区。 //实际接收到的有效字节数 //Receive也是个卡线程的方法
Console.WriteLine("等待接受客户端的数据:"); int dataLength =
clientSocket.Receive(buffer); Console.WriteLine("接受到客户端的数据,字节数:" + dataLength);
//如果客户端关闭,发送的数据就为空,就跳出循环 if (dataLength == 0) { break; }
//假设收到的是个字符串(先这么假定),转成字符串处理 string strMsg = Encoding.UTF8.GetString(buffer, 1,
dataLength - 1); Console.WriteLine("接受到客户端的消息:" + strMsg); } //中止当前线程
Thread.CurrentThread.Abort(); } catch(Exception e) { SocketException socketExp
= e as SocketException; if (socketExp!=null && socketExp.NativeErrorCode ==
10054) { Console.WriteLine("socket客户端关闭:" + e.ToString()); } else {
Console.WriteLine("======接受消息异常:" + e.ToString()); } //中止当前线程
Thread.CurrentThread.Abort(); } }

就这样一个简易的socket服务器就搭建起来了。

调用方式:
SGSocketServer socketServer = new SGSocketServer(); socketServer.Start();
当然,要达到工程应用级别,还要做更多一些工作。但千里之行始于足下,有了这个基础之后就可以不断地往里面添加业务逻辑。

技术
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:766591547
关注微信