【C#】一文教你搭个简易的Socket服务器
【C#】一文教你搭个简易的Socket服务器
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);//获取IPIPAddress 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();
当然,要达到工程应用级别,还要做更多一些工作。但千里之行始于足下,有了这个基础之后就可以不断地往里面添加业务逻辑。