0

0

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

黄舟

黄舟

发布时间:2017-02-27 11:16:18

|

2119人浏览过

|

来源于php中文网

原创

本文介绍

在上一篇博客中我说了,我将会介绍c#中使用socket和tcplistener和udpclient实现各种同步和异步的tcp和udp服务器,这些都是是我自己花了很多天的时间来总结的,这样一来相信刚接触c#网络编程的朋友们不会像以前的我一样到处出找资料,到处调试。本次我介绍的是使用socket来实现的同步的tcp服务器,同步的tcp服务器和第一篇里面介绍的异步tcp服务器的区别就是,在socket调用accept的时候是否会阻塞。

同步的TCP服务器在接受到一个客户端的请求的时候一般是开启一个线程去处理和这个客户端的通信工作,这种方式的不好的地方就是资源消耗大,但是假如使用线程池的话,事先分配一定数量的线程,性能还是可以。

但是我之所以给出很多方法实现的服务器,主要目的就是想测试哪种情况性能比较不错,就目前来看,异步的模式比较NICE,但是其实还有一种IOCP模式性能是最好的。。。

Socket同步TCP服务器

服务端代码

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

namespace NetFrame.Net.TCP.Sock.Synchronous
{
    /// 
    /// 基于socket实现的同步TCP服务器
    /// 
    public class SocketTCPServer
    {
        #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 SocketTCPServer(int listenPort)
            : this(IPAddress.Any, listenPort, 1024)
        {
        }

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

        /// 
        /// 同步Socket TCP服务器
        /// 
        /// 监听的IP地址
        /// 监听的端口
        /// 最大客户端数量
        public SocketTCPServer(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));
                Thread thread = new Thread(StartListen);
                thread.Start();

            }
        }
        /// 
        /// 开始进行监听
        /// 
        private void StartListen()
        {
            _serverSock.Listen(1024);
            SocketClientHandle handle;
            while (IsRunning)
            {
                if (_clientCount >= _maxClient)
                {
                    //TODO 客户端过多异常
                    RaiseOtherException(null);
                }
                else
                {
                    Socket clientSock = _serverSock.Accept();
                    _clientCount++;
                    //TODO 创建一个处理客户端的线程并启动
                    handle = new SocketClientHandle(clientSock);
                    _clients.Add(handle);
                    //使用线程池来操作
                    ThreadPool.QueueUserWorkItem(new WaitCallback(handle.RecevieData));

                    //Thread pthread;
                    //pthread = new Thread(new ThreadStart(client.RecevieData));
                    //pthread.Start();
                    //这里应该使用线程池来进行
                }
            }

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

            }
        }
        /// 
        /// 发送函数
        /// 
        public void Send(string msg, SocketClientHandle client)
        {
            //TODO
        }

        /// 
        /// 关闭一个与客户端之间的会话
        /// 
        /// 需要关闭的客户端会话对象
        public void Close(SocketClientHandle handle)
        {
            if (handle != null)
            {
                _clients.Remove(handle);
                handle.Dispose();
                _clientCount--;
                //TODO 触发关闭事件
                
            }
        }
        /// 
        /// 关闭所有的客户端会话,与所有的客户端连接会断开
        /// 
        public void CloseAllClient()
        {
            foreach (SocketClientHandle handle in _clients)
            {
                Close(handle);
            }
            _clientCount = 0;
            _clients.Clear();
        }

        #endregion

        #region 事件

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

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

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

        private void RaiseDataReceived(SocketClientHandle handle)
        {
            if (DataReceived != null)
            {
                DataReceived(this, new SocketEventArgs(handle));
            }
        }

        /// 
        /// 数据发送事件
        /// 
        public event EventHandler CompletedSend;

        /// 
        /// 触发数据发送事件
        /// 
        /// 
        private void RaiseCompletedSend(SocketClientHandle handle)
        {
            if (CompletedSend != null)
            {
                CompletedSend(this, new SocketEventArgs(handle));
            }
        }


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

        /// 
        /// 异常事件
        /// 
        public event EventHandler OtherException;
        /// 
        /// 触发异常事件
        /// 
        /// 
        private void RaiseOtherException(SocketClientHandle handle, string descrip)
        {
            if (OtherException != null)
            {
                OtherException(this, new SocketEventArgs(descrip, handle));
            }
        }
        private void RaiseOtherException(SocketClientHandle handle)
        {
            RaiseOtherException(handle, "");
        }

        #endregion

        #region Close 未实现
        #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 异常
                    }
                }
                disposed = true;
            }
        }
        #endregion
    }
}


对客户端操作封装的Handle类

剪映
剪映

一款全能易用的桌面端剪辑软件

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

namespace NetFrame.Net.TCP.Sock.Synchronous
{
    /// 
    /// Socket 服务器用于处理客户端连接封装的客户端处理类
    /// 
    public class SocketClientHandle:IDisposable
    {
        /// 
        /// 与客户端相关联的socket
        /// 
        private Socket _client;

        /// 
        /// 标识是否与客户端相连接
        /// 
        private bool _is_connect;
        public bool IsConnect
        {
            get { return _is_connect; }
            set { _is_connect = value; }
        }

        /// 
        /// 数据接受缓冲区
        /// 
        private byte[] _recvBuffer;

        public SocketClientHandle(Socket client)
        {
            this._client = client;
            _is_connect = true;
            _recvBuffer = new byte[1024 * 1024 * 2];
        }

        #region Method
        /// 
        /// 接受来自客户端发来的数据
        /// 
        public void RecevieData(Object state)
        {
            int len = -1;
            while (_is_connect)
            {
                try
                {
                    len = _client.Receive(_recvBuffer);
                }
                catch (Exception)
                {
                    //TODO
                }
            }
        }

        /// 
        /// 向客户端发送数据
        /// 
        public void SendData(string msg)
        {
            byte[] data = Encoding.Default.GetBytes(msg);
            try
            {
                //有一种比较好的写法
                _client.Send(data);
            }
            catch (Exception)
            {
                //TODO 处理异常
            }
        }

        #endregion


        #region 事件


        //TODO 消息发送事件
        //TODO 数据收到事件
        //TODO 异常处理事件

        #endregion

        #region 释放
        /// 
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// 
        public void Dispose()
        {
            _is_connect = false;
            if (_client != null)
            {
                _client.Close();
                _client = null;
            }
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}


Socket同步TCP服务器的时间参数类

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

namespace NetFrame.Net.TCP.Sock.Synchronous
{
    /// 
    /// 同步Socket TCP服务器事件类
    /// 
    public class SocketEventArgs : EventArgs
    {
        /// 
        /// 提示信息
        /// 
        public string _msg;

        /// 
        /// 客户端状态封装类
        /// 
        public SocketClientHandle _handle;

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

        public SocketEventArgs(string msg)
        {
            this._msg = msg;
            IsHandled = false;
        }
        public SocketEventArgs(SocketClientHandle handle)
        {
            this._handle = handle;
            IsHandled = false;
        }
        public SocketEventArgs(string msg, SocketClientHandle handle)
        {
            this._msg = msg;
            this._handle = handle;
            IsHandled = false;
        }
    }
}

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


热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

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

20

2026.01.29

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

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

18

2026.01.29

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

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

19

2026.01.29

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

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

3

2026.01.29

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

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

6

2026.01.29

热门下载

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

精品课程

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

共94课时 | 8万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

C++教程
C++教程

共115课时 | 14.9万人学习

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

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