0

0

C#网络编程系列文章(一)之Socket实现异步TCP服务器

黄舟

黄舟

发布时间:2017-02-27 11:14:49

|

1858人浏览过

|

来源于php中文网

原创

开篇

本人因为对于网络编程的喜爱,经常性的使用c#编写各类服务器(e.g tcp服务器,udp服务器),但是基本上都是搞着玩,网上也有很多讲c#网络编程的文章,当然我也参考了很多作者写的文章。看了这篇文章以后再也不用导出找资料了。微笑

本系列文章会依次介绍使用Socket实现的异步TCP服务器同步TCP服务器异步UDP服务器同步UDP服务器 and 使用TcpListener和UdpClient实现的异步TCP服务器同步TCP服务器异步UDP服务器同步UDP服务器

Socket异步TCP服务器

相信搞过网络编程的人来说这个TCP一点也不陌生吧,在C#中微软已经帮我们封装过了一个TcpListener和TcpClient这两个类了,实现了对于套接字的封装,但是呢实际上还是不怎么好用,所以我们用Socket来实现一个异步的TCP服务器。

在本文中我只给出服务器端代码,客户端代码自己可以找找别处,毕竟我只是为了写出一个好的服务器端

下面是代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace NetFrame.Net.TCP.Sock.Asynchronous
{
    /// 
    /// Socket实现的异步TCP服务器
    /// 
    public class AsyncSocketTCPServer : IDisposable
    {
        #region Fields
        /// 
        /// 服务器程序允许的最大客户端连接数
        /// 
        private int _maxClient;

        /// 
        /// 当前的连接的客户端数
        /// 
        private int _clientCount;

        /// 
        /// 服务器使用的异步socket
        /// 
        private Socket _serverSock;

        /// 
        /// 客户端会话列表
        /// 
        private List _clients;

        private bool disposed = false;

        #endregion

        #region Properties

        /// 
        /// 服务器是否正在运行
        /// 
        public bool IsRunning { get; private set; }
        /// 
        /// 监听的IP地址
        /// 
        public IPAddress Address { get; private set; }
        /// 
        /// 监听的端口
        /// 
        public int Port { get; private set; }
        /// 
        /// 通信使用的编码
        /// 
        public Encoding Encoding { get; set; }


        #endregion

        #region 构造函数

        /// 
        /// 异步Socket TCP服务器
        /// 
        /// 监听的端口
        public AsyncSocketTCPServer(int listenPort)
            : this(IPAddress.Any, listenPort,1024)
        {
        }

        /// 
        /// 异步Socket TCP服务器
        /// 
        /// 监听的终结点
        public AsyncSocketTCPServer(IPEndPoint localEP)
            : this(localEP.Address, localEP.Port,1024)
        {
        }

        /// 
        /// 异步Socket TCP服务器
        /// 
        /// 监听的IP地址
        /// 监听的端口
        /// 最大客户端数量
        public AsyncSocketTCPServer(IPAddress localIPAddress, int listenPort,int maxClient)
        {
            this.Address = localIPAddress;
            this.Port = listenPort;
            this.Encoding = Encoding.Default;

            _maxClient = maxClient;
            _clients = new List();
            _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }

        #endregion

        #region Method

        /// 
        /// 启动服务器
        /// 
        public void Start()
        {
            if (!IsRunning)
            {
                IsRunning = true;
                _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                _serverSock.Listen(1024);
                _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
            }
        }

        /// 
        /// 启动服务器
        /// 
        /// 
        /// 服务器所允许的挂起连接序列的最大长度
        /// 
        public void Start(int backlog)
        {
            if (!IsRunning)
            {
                IsRunning = true;
                _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                _serverSock.Listen(backlog);
                _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
            }
        }

        /// 
        /// 停止服务器
        /// 
        public void Stop()
        {
            if (IsRunning)
            {
                IsRunning = false;
                _serverSock.Close();
                //TODO 关闭对所有客户端的连接

            }
        }

        /// 
        /// 处理客户端连接
        /// 
        /// 
        private void HandleAcceptConnected(IAsyncResult ar)
        {
            if (IsRunning)
            {
                Socket server = (Socket)ar.AsyncState;
                Socket client = server.EndAccept(ar);

                //检查是否达到最大的允许的客户端数目
                if (_clientCount >= _maxClient)
                {
                    //C-TODO 触发事件
                    RaiseOtherException(null);
                }
                else
                {
                    AsyncSocketState state = new AsyncSocketState(client);
                    lock (_clients)
                    {
                        _clients.Add(state);
                        _clientCount++;
                        RaiseClientConnected(state); //触发客户端连接事件
                    }
                    state.RecvDataBuffer = new byte[client.ReceiveBufferSize];
                    //开始接受来自该客户端的数据
                    client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,
                     new AsyncCallback(HandleDataReceived), state);
                }
                //接受下一个请求
                server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);
            }
        }
        /// 
        /// 处理客户端数据
        /// 
        /// 
        private void HandleDataReceived(IAsyncResult ar)
        {
            if (IsRunning)
            {
                AsyncSocketState state = (AsyncSocketState)ar.AsyncState;
                Socket client = state.ClientSocket;
                try
                {
                    //如果两次开始了异步的接收,所以当客户端退出的时候
                    //会两次执行EndReceive
                    int recv = client.EndReceive(ar);
                    if (recv == 0)
                    {
                        //C- TODO 触发事件 (关闭客户端)
                        Close(state);
                        RaiseNetError(state);
                        return;
                    }
                    //TODO 处理已经读取的数据 ps:数据在state的RecvDataBuffer中

                    //C- TODO 触发数据接收事件
                    RaiseDataReceived(state);
                }
                catch (SocketException)
                {
                    //C- TODO 异常处理
                    RaiseNetError(state);
                }
                finally
                {
                    //继续接收来自来客户端的数据
                    client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,
                     new AsyncCallback(HandleDataReceived), state);
                }
            }
        }

        /// 
        /// 发送数据
        /// 
        /// 接收数据的客户端会话
        /// 数据报文
        public void Send(AsyncSocketState state, byte[] data)
        {
            RaisePrepareSend(state);
            Send(state.ClientSocket, data);
        }

        /// 
        /// 异步发送数据至指定的客户端
        /// 
        /// 客户端
        /// 报文
        public void Send(Socket client, byte[] data)
        {
            if (!IsRunning)
                throw new InvalidProgramException("This TCP Scoket server has not been started.");

            if (client == null)
                throw new ArgumentNullException("client");

            if (data == null)
                throw new ArgumentNullException("data");
            client.BeginSend(data, 0, data.Length, SocketFlags.None,
             new AsyncCallback(SendDataEnd), client);
        }

        /// 
        /// 发送数据完成处理函数
        /// 
        /// 目标客户端Socket
        private void SendDataEnd(IAsyncResult ar)
        {
            ((Socket)ar.AsyncState).EndSend(ar);
            RaiseCompletedSend(null);
        }
        #endregion

        #region 事件

        /// 
        /// 与客户端的连接已建立事件
        /// 
        public event EventHandler ClientConnected;
        /// 
        /// 与客户端的连接已断开事件
        /// 
        public event EventHandler ClientDisconnected;

        /// 
        /// 触发客户端连接事件
        /// 
        /// 
        private void RaiseClientConnected(AsyncSocketState state)
        {
            if (ClientConnected != null)
            {
                ClientConnected(this, new AsyncSocketEventArgs(state));
            }
        }
        /// 
        /// 触发客户端连接断开事件
        /// 
        /// 
        private void RaiseClientDisconnected(Socket client)
        {
            if (ClientDisconnected != null)
            {
                ClientDisconnected(this, new AsyncSocketEventArgs("连接断开"));
            }
        }

        /// 
        /// 接收到数据事件
        /// 
        public event EventHandler DataReceived;

        private void RaiseDataReceived(AsyncSocketState state)
        {
            if (DataReceived != null)
            {
                DataReceived(this, new AsyncSocketEventArgs(state));
            }
        }

        /// 
        /// 发送数据前的事件
        /// 
        public event EventHandler PrepareSend;

        /// 
        /// 触发发送数据前的事件
        /// 
        /// 
        private void RaisePrepareSend(AsyncSocketState state)
        {
            if (PrepareSend != null)
            {
                PrepareSend(this, new AsyncSocketEventArgs(state));
            }
        }

        /// 
        /// 数据发送完毕事件
        /// 
        public event EventHandler CompletedSend;
        
        /// 
        /// 触发数据发送完毕的事件
        /// 
        /// 
        private void RaiseCompletedSend(AsyncSocketState state)
        {
            if (CompletedSend != null)
            {
                CompletedSend(this, new AsyncSocketEventArgs(state));
            }
        }

        /// 
        /// 网络错误事件
        /// 
        public event EventHandler NetError;
        /// 
        /// 触发网络错误事件
        /// 
        /// 
        private void RaiseNetError(AsyncSocketState state)
        {
            if (NetError != null)
            {
                NetError(this, new AsyncSocketEventArgs(state));
            }
        }

        /// 
        /// 异常事件
        /// 
        public event EventHandler OtherException;
        /// 
        /// 触发异常事件
        /// 
        /// 
        private void RaiseOtherException(AsyncSocketState state, string descrip)
        {
            if (OtherException != null)
            {
                OtherException(this, new AsyncSocketEventArgs(descrip, state));
            }
        }
        private void RaiseOtherException(AsyncSocketState state)
        {
            RaiseOtherException(state, "");
        }
        #endregion

        #region Close
        /// 
        /// 关闭一个与客户端之间的会话
        /// 
        /// 需要关闭的客户端会话对象
        public void Close(AsyncSocketState state)
        {
            if (state != null)
            {
                state.Datagram = null;
                state.RecvDataBuffer = null;

                _clients.Remove(state);
                _clientCount--;
                //TODO 触发关闭事件
                state.Close();
            }
        }
        /// 
        /// 关闭所有的客户端会话,与所有的客户端连接会断开
        /// 
        public void CloseAllClient()
        {
            foreach (AsyncSocketState client in _clients)
            {
                Close(client);
            }
            _clientCount = 0;
            _clients.Clear();
        }
        #endregion

        #region 释放
        /// 
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// 
        /// Releases unmanaged and - optionally - managed resources
        /// 
        /// true to release 
        /// both managed and unmanaged resources; false 
        /// to release only unmanaged resources.
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    try
                    {
                        Stop();
                        if (_serverSock != null)
                        {
                            _serverSock = null;
                        }
                    }
                    catch (SocketException)
                    {
                        //TODO
                        RaiseOtherException(null);
                    }
                }
                disposed = true;
            }
        }
        #endregion
    }
}


事件参数类

SEEK.ai
SEEK.ai

AI驱动的智能数据解决方案,询问您的任何数据并立即获得答案

下载
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NetFrame.Net.TCP.Sock.Asynchronous
{
    /// 
    /// 异步Socket TCP事件参数类
    /// 
    public class AsyncSocketEventArgs:EventArgs
    {
        /// 
        /// 提示信息
        /// 
        public string _msg;

        /// 
        /// 客户端状态封装类
        /// 
        public AsyncSocketState _state;

        /// 
        /// 是否已经处理过了
        /// 
        public bool IsHandled { get; set; }

        public AsyncSocketEventArgs(string msg)
        {
            this._msg = msg;
            IsHandled = false;
        }
        public AsyncSocketEventArgs(AsyncSocketState state)
        {
            this._state = state;
            IsHandled = false;
        }
        public AsyncSocketEventArgs(string msg, AsyncSocketState state)
        {
            this._msg = msg;
            this._state = state;
            IsHandled = false;
        }
    }
}


用户状态封装

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace NetFrame.Net.TCP.Sock.Asynchronous
{
    /// 
    /// 异步SOCKET TCP 中用来存储客户端状态信息的类
    /// 
    public class AsyncSocketState
    {
        #region 字段
        /// 
        /// 接收数据缓冲区
        /// 
        private byte[] _recvBuffer;

        /// 
        /// 客户端发送到服务器的报文
        /// 注意:在有些情况下报文可能只是报文的片断而不完整
        /// 
        private string _datagram;

        /// 
        /// 客户端的Socket
        /// 
        private Socket _clientSock;

        #endregion

        #region 属性

        /// 
        /// 接收数据缓冲区 
        /// 
        public byte[] RecvDataBuffer
        {
            get
            {
                return _recvBuffer;
            }
            set
            {
                _recvBuffer = value;
            }
        }

        /// 
        /// 存取会话的报文
        /// 
        public string Datagram
        {
            get
            {
                return _datagram;
            }
            set
            {
                _datagram = value;
            }
        }

        /// 
        /// 获得与客户端会话关联的Socket对象
        /// 
        public Socket ClientSocket
        {
            get
            {
                return _clientSock;

            }
        }


        #endregion

        /// 
        /// 构造函数
        /// 
        /// 会话使用的Socket连接
        public AsyncSocketState(Socket cliSock)
        {
            _clientSock = cliSock;
        }

        /// 
        /// 初始化数据缓冲区
        /// 
        public void InitBuffer()
        {
            if (_recvBuffer == null&&_clientSock!=null)
            {
                _recvBuffer=new byte[_clientSock.ReceiveBufferSize];
            }
        }

        /// 
        /// 关闭会话
        /// 
        public void Close()
        {

            //关闭数据的接受和发送
            _clientSock.Shutdown(SocketShutdown.Both);

            //清理资源
            _clientSock.Close();
        }
    }
}

 以上就是C#网络编程系列文章(一)之Socket实现异步TCP服务器的内容,更多相关内容请关注PHP中文网(www.php.cn)!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

2

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

2

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

0

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

0

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.29

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

25

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

16

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

8

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

622

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.9万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

C++教程
C++教程

共115课时 | 14.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号