本文灵感来自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) 的设计方法实现的异步操作。

界面简单如下:

主要代码如下:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
 
namespace Chatting
{
    public abstract class SocketFunc
    {
        //不管是服务端还是客户端, 建立连接后用这个Socket进行通信
        public Socket communicateSocket = null;
 
        //服务端和客户端建立连接的方式稍有不同, 子类会重载
        public abstract void Access(string IP, System.Action AccessAciton);
 
        //发送消息的函数
        public void Send(string message)
        {
            if (communicateSocket.Connected == false)
            {
                throw new Exception("还没有建立连接, 不能发送消息");
            }
            Byte[] msg = Encoding.UTF8.GetBytes(message);
            communicateSocket.BeginSend(msg,0, msg.Length, SocketFlags.None,
                ar => {
                 
                }, null);
        }
 
        //接受消息的函数
        public void Receive(System.Action<string> ReceiveAction)
        {
            //如果消息超过1024个字节, 收到的消息会分为(总字节长度/1024 +1)条显示
            Byte[] msg = new byte[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);
        }
    }
 
 
    public class ServerSocket:SocketFunc
    {
        //服务端重载Access函数
        public override void Access(string IP, System.Action AccessAciton)
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //本机预使用的IP和端口
            IPEndPoint serverIP = new IPEndPoint(IPAddress.Any, 9050);
            //绑定服务端设置的IP
            serverSocket.Bind(serverIP);
            //设置监听个数
            serverSocket.Listen(1);
            //异步接收连接请求
            serverSocket.BeginAccept(ar =>
                {
                    base.communicateSocket = serverSocket.EndAccept(ar);
                    AccessAciton();
                }, null);
        }
    }
 
    public class ClientSocket:SocketFunc
    {
        //客户端重载Access函数
        public override void Access(string IP, System.Action AccessAciton)
        {
            base.communicateSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            base.communicateSocket.Bind(new IPEndPoint(IPAddress.Any, 9051));
             
            //服务器的IP和端口
            IPEndPoint serverIP;
            try
            {
                serverIP = new IPEndPoint(IPAddress.Parse(IP), 9050);
            }
            catch
            {
                throw new Exception(String.Format("{0}不是一个有效的IP地址!", IP));
            }
             
            //客户端只用来向指定的服务器发送信息,不需要绑定本机的IP和端口,不需要监听
            try
            {
                base.communicateSocket.BeginConnect(serverIP, ar =>
                {
                    AccessAciton();
                }, null);
            }
            catch
            {
                throw new Exception(string.Format("尝试连接{0}不成功!", IP));
            }
        }
    }
}

相关的事件处理程序,如下:


效果,如下:

异步Socket服务器与客户端的更多相关文章

  1. 可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui)

    可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui) 0 前言 >>[前言].[第1节].[第2节].[第3节]. ...

  2. 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 ...

  3. c#Socket服务器与客户端的开发(1)

    上个项目中用到了Socket通讯,项目中直接借助SuperSocket实现,但是我觉得这毕竟是一个我没接触过的东西,所以也顺便学习了一下原生socket的使用,做了一个socket服务器与客户端的开发 ...

  4. 可扩展多线程异步Socket服务器框架EMTASS 2.0 续

    转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ...

  5. C#实现的异步Socket服务器

    介绍 我最近需要为一个.net项目准备一个内部线程通信机制. 项目有多个使用ASP.NET,Windows 表单和控制台应用程序的服务器和客户端构成. 考虑到实现的可能性,我下定决心要使用原生的soc ...

  6. C# 实现的异步 Socket 服务器

    介绍 我最近需要为一个.net项目准备一个内部线程通信机制. 项目有多个使用ASP.NET,Windows 表单和控制台应用程序的服务器和客户端构成. 考虑到实现的可能性,我下定决心要使用原生的soc ...

  7. 可扩展多线程异步Socket服务器框架EMTASS 2.0

    0 前言 >>[前言].[第1节].[第2节].[第3节].[第4节].[第5节].[第6节] 在程序设计与实际应用中,Socket数据包接收服务器够得上一个经典问题了:需要计算机与网络编 ...

  8. c#Socket服务器与客户端的开发(2)

    上一篇文章我们使用原生的socket分别实现了服务器和客户端, 本篇文章使用SuperSocket来开发实现服务器, 之前也介绍了SuperSocket是一个轻量级, 跨平台而且可扩展的 .Net/M ...

  9. 一个 Java 的 Socket 服务器和客户端通信的例子

    一个 HelloWord 级别的 Java Socket 通信的例子.通讯过程: 先启动 Server 端,进入一个死循环以便一直监听某端口是否有连接请求.然后运行 Client 端,客户端发出连接请 ...

随机推荐

  1. 浅谈musql中using的使用---高性能(三)

    转载地址:https://blog.csdn.net/lppl010_/article/details/79429657 mysql中using的用法为: using()用于两张表的join查询,要求 ...

  2. css 初始包含块

    continuous media ,paged media 关于continuous media[连续媒体]和paged media[分页媒体] 直白的讲,continuous和paged media ...

  3. 猎豹浏览器(chrome内核)屏蔽视频广告

    1.基于猎豹浏览器(原则上chrome内核浏览器都可以) 2.下载插件Adblock Plus,下载地址:http://chromecj.com/productivity/2014-07/24/dow ...

  4. 团队作业之现场UML设计

    项目UML设计(团队) 团队信息 团队名:第三视角 各成员学号及姓名 姓名 学号 博客链接 张扬(组长) 031602345 http://www.cnblogs.com/sxZhangYang/p/ ...

  5. 去除字符串中的emoji字符

    对于使用utf8编码的mysql数据库来说,如果字符串中存在emoji小图像,是不能存进数据库中的,查了一下,原因大概是因为utf8编码可以存1-3个字节的字符,但是emoji是4个字节:解决方法可以 ...

  6. L226

    The dean can’t see you at the moment. He is addressing the first-year students in the lecture hall.系 ...

  7. L224

    Astronomers have revealed details of mysterious signals emanating from a distant galaxy, picked up b ...

  8. <constant name="struts.devMode" value="false" />

    在开发中,我们常常会遇到<constant name="struts.devMode" value="false" />,这是struts2的特性, ...

  9. makefile的一个错误:*** missing separator

    原文转自:http://blog.sina.com.cn/s/blog_87c063060101c9yp.html 1.在写 多目录下makefile的时候,碰到一个错误提示,让我纠结许久,后面还是解 ...

  10. 解决:编辑一条彩信,附件选择添加音频,返回到编辑界面选择play,不能播放,没有声音

    [操作步骤]:编辑一条彩信,附件选择添加音频(外部音频),返回到编辑界面选择play,菜单键选择view slideshow [测试结果]:不能播放,没有声音 [预期结果]:可以播放 根据以往的经验( ...