异步Socket服务器与客户端
本文灵感来自Andre Azevedo 在CodeProject上面的一片文章,An Asynchronous Socket Server and Client,讲的是异步的Socket通信。
- Socket连接(Socket Connection)
- Socket服务(Socket Service)
- 连接主机(Connection Host)
- 加密与压缩(Encrypt与Compress)
- 请求入队(Enqueuing Requests)
- 确保发送和接收(Ensure send and recieve)
- 检查消息头(Check message header)
- 检查空闲连接(Checking idle connections)
- 加密服务
- SSL认证(SSL authentication)
- 对称认证(Symmetric authentication)
- 连接创建者(Connection Creator)
- Socket服务器与Socket侦听者(SocketServer and SocketListener)
- Socket服务器构造函数与方法(SocketServer constructor and methods)
- Socket客户端与Socket连接者(SocketClient and SocketConnector)
- Socket客户端构造函数与方法(SocketClient constructor and methods)
- 应答演示项目(Echo Demo Project)
- 主机(Hosts)
- 服务(Services)
- 结语(Conclusion)
- 版本历史(History)
本文仅实现一个相对简单的异步Socket服务器与客户端通信示例。
首先需要说明如下2个问题
1.同步、异步、多线程是什么关系?答:同步是等待返回,相当于阻塞式;异步是不等待返回,是非阻塞式,可以用多线程实现。
2.有些异步方法有两种实现方式, 如BeginAccept()和AcceptAsync(), 这两个方法有什么区别呢?答: 以 Begin 和 End 开头的方法是以 APM(Asynchronous Programming Model)设计方法实现的异步操作, 以 Async 结尾的方法是利用称为 EAP (Event-based Asynchronous Pattern) 的设计方法实现的异步操作。
界面简单如下:

主要代码如下:
| usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;namespaceChatting{    publicabstractclassSocketFunc    {        //不管是服务端还是客户端, 建立连接后用这个Socket进行通信        publicSocket communicateSocket = null;        //服务端和客户端建立连接的方式稍有不同, 子类会重载        publicabstractvoidAccess(stringIP, System.Action AccessAciton);        //发送消息的函数        publicvoidSend(stringmessage)        {            if(communicateSocket.Connected == false)            {                thrownewException("还没有建立连接, 不能发送消息");            }            Byte[] msg = Encoding.UTF8.GetBytes(message);            communicateSocket.BeginSend(msg,0, msg.Length, SocketFlags.None,                ar => {                                }, null);        }        //接受消息的函数        publicvoidReceive(System.Action<string> ReceiveAction)        {            //如果消息超过1024个字节, 收到的消息会分为(总字节长度/1024 +1)条显示            Byte[] msg = newbyte[1024];            //异步的接受消息            communicateSocket.BeginReceive(msg, 0, msg.Length, SocketFlags.None,                ar => {                    //对方断开连接时, 这里抛出Socket Exception                    //An existing connection was forcibly closed by the remote host                         communicateSocket.EndReceive(ar);                     ReceiveAction(Encoding.UTF8.GetString(msg).Trim('\0',' '));                    Receive(ReceiveAction);                }, null);        }    }    publicclassServerSocket:SocketFunc    {        //服务端重载Access函数        publicoverridevoidAccess(stringIP, System.Action AccessAciton)        {            Socket serverSocket = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //本机预使用的IP和端口            IPEndPoint serverIP = newIPEndPoint(IPAddress.Any, 9050);            //绑定服务端设置的IP            serverSocket.Bind(serverIP);            //设置监听个数            serverSocket.Listen(1);            //异步接收连接请求            serverSocket.BeginAccept(ar =>                {                    base.communicateSocket = serverSocket.EndAccept(ar);                    AccessAciton();                }, null);        }    }    publicclassClientSocket:SocketFunc    {        //客户端重载Access函数        publicoverridevoidAccess(stringIP, System.Action AccessAciton)        {            base.communicateSocket = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            base.communicateSocket.Bind(newIPEndPoint(IPAddress.Any, 9051));                        //服务器的IP和端口            IPEndPoint serverIP;            try            {                serverIP = newIPEndPoint(IPAddress.Parse(IP), 9050);            }            catch            {                thrownewException(String.Format("{0}不是一个有效的IP地址!", IP));            }                        //客户端只用来向指定的服务器发送信息,不需要绑定本机的IP和端口,不需要监听            try            {                base.communicateSocket.BeginConnect(serverIP, ar =>                {                    AccessAciton();                }, null);            }            catch            {                thrownewException(string.Format("尝试连接{0}不成功!", IP));            }        }    }} | 
相关的事件处理程序,如下:
效果,如下:

异步Socket服务器与客户端的更多相关文章
- 可扩展多线程异步Socket服务器框架EMTASS 2.0   (转自:http://blog.csdn.net/hulihui)
		可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui) 0 前言 >>[前言].[第1节].[第2节].[第3节]. ... 
- Ajax跨域问题及解决方案  asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS)   c#中的Cache缓存技术   C#中的Cookie   C#串口扫描枪的简单实现   c#Socket服务器与客户端的开发(2)
		Ajax跨域问题及解决方案 目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ... 
- c#Socket服务器与客户端的开发(1)
		上个项目中用到了Socket通讯,项目中直接借助SuperSocket实现,但是我觉得这毕竟是一个我没接触过的东西,所以也顺便学习了一下原生socket的使用,做了一个socket服务器与客户端的开发 ... 
- 可扩展多线程异步Socket服务器框架EMTASS 2.0 续
		转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ... 
- C#实现的异步Socket服务器
		介绍 我最近需要为一个.net项目准备一个内部线程通信机制. 项目有多个使用ASP.NET,Windows 表单和控制台应用程序的服务器和客户端构成. 考虑到实现的可能性,我下定决心要使用原生的soc ... 
- C# 实现的异步 Socket 服务器
		介绍 我最近需要为一个.net项目准备一个内部线程通信机制. 项目有多个使用ASP.NET,Windows 表单和控制台应用程序的服务器和客户端构成. 考虑到实现的可能性,我下定决心要使用原生的soc ... 
- 可扩展多线程异步Socket服务器框架EMTASS 2.0
		0 前言 >>[前言].[第1节].[第2节].[第3节].[第4节].[第5节].[第6节] 在程序设计与实际应用中,Socket数据包接收服务器够得上一个经典问题了:需要计算机与网络编 ... 
- c#Socket服务器与客户端的开发(2)
		上一篇文章我们使用原生的socket分别实现了服务器和客户端, 本篇文章使用SuperSocket来开发实现服务器, 之前也介绍了SuperSocket是一个轻量级, 跨平台而且可扩展的 .Net/M ... 
- 一个 Java 的 Socket 服务器和客户端通信的例子
		一个 HelloWord 级别的 Java Socket 通信的例子.通讯过程: 先启动 Server 端,进入一个死循环以便一直监听某端口是否有连接请求.然后运行 Client 端,客户端发出连接请 ... 
随机推荐
- POJ 1128 拓扑排序 + 深搜
			/* (⊙v⊙)嗯 貌似是一个建图 拓扑+深搜的过程.至于为什么要深搜嘛..一个月前敲得题现在全部推了重敲,于是明白了.因为题意要求如果有多个可能的解的话. * 就要输出字典序最小的那个.所以可以对2 ... 
- cookie  -- 添加删除
			前段时间学到了cookie,之前的公司用的jquery插件,现在终于学到了原生的js <!doctype html> <html> <head> <meta ... 
- git and github问题集锦
			本人遇到的: 
- TADOTABLE 永久字段的顺序 和 AppendRecord
			AppendRecord 方法,添加记录的字段到数据库里时,是按照IDE里永久字段的顺序,不是数据库表里的字段顺序. 自动编号 字段,以nil为值. 日期时间 字段,直接now 写法 
- struts2 的学习
			1.struts.xml 中的action不是代表一个action类(控制器),而是代表一次访问,所以action的name属性和访问路径有关.配置文件中的package的namespace属性其实就 ... 
- 第一章连通性问题-----algorithm in C 读书笔记
			首先不得不吐槽一下翻译的质量,霍红卫....你给我站出来,不打死你,只想问你一下,你当年四级过了吗? 问题描述 输入两个整数,代表两个节点,如果这两个整数没有建立连接(这包括直接连接和通过其他节点连接 ... 
- mysql_query — 发送一条 MySQL 查询
			仅对 SELECT,SHOW,EXPLAIN 或 DESCRIBE 语句返回 一个资源标识符,如果查询执行不正确则返回 FALSE.对于 其它类型的 SQL 语句,在执行成功时返回 TRUE,出错时返 ... 
- 题目1001:A+B for Matrices
			题目1001:A+B for Matrices 时间限制:1 秒内存限制:32 兆 题目描述: This time, you are supposed to find A+B where A and ... 
- C++ 多线程中使用cout还是printf
			在多线程的设计模式下,如果多个线程都使用cout打印信息,那么很容易出现内容交替的现象,例如下图: 代码如下: 如果把cout替换成printf,那么就不会出现这个问题,运行结果如下图: 对应代码如下 ... 
- Nginx+Keepalive实现高可用负载均衡
			1.准备2台服务器 服务器名LB1,假设IP为192.168.1.100 服务器名LB2,假设IP为192.168.1.101 2.在LB1,LB2上分别安装Nginx 步骤参照:http://blo ... 
