当前位置: 代码网 > it编程>编程语言>Asp.net > C#中Socket通信编程的异步实现流程分析

C#中Socket通信编程的异步实现流程分析

2024年12月21日 Asp.net 我要评论
什么是socket编程的异步是实现所谓socket编程的异步实现是指按照异步过程来实现socket编程,那么什么是异步过程呢,我们把在完成了一次调用后通过状态、通知和回调来告知调用者的方式成为异步过程

什么是socket编程的异步是实现

所谓socket编程的异步实现是指按照异步过程来实现socket编程,那么什么是异步过程呢,我们把在完成了一次调用后通过状态、通知和回调来告知调用者的方式成为异步过程,换句话说,在异步过程中当调用一个方法时,调用者并不能够立刻得到结果,只有当这个方法调用完毕后调用者才能获得调用结果。这样做的好处是什么呢?答案是高效。相信大家还记得我们在《c#中socket通信编程的同步实现》这篇文章中使用多线程来实现简单聊天的案例吧,在这个案例中我们需要开启两个线程来不断监听客户端的连接和客户端的消息,这样的效率肯定是很低的。那么现在好了,我们可以通过异步过程来解决这个问题,下面我们就来看看如何实现socket的异步通信。

如何实现socket异步通信

服务端

基本流程

  • 创建套接字
  • 绑定套接字的ip和端口号——bind()
  • 使套接字处于监听状态等待客户端的连接请求——listen()
  • 当请求到来后,使用beginaccept()和endaccept()方法接受请求,返回新的套接字
  • 使用beginsend()/endsend和beginreceive()/endreceive()两组方法与客户端进行收发通信
  • 返回,再次等待新的连接请求
  • 关闭套接字

代码示例

using system;
using system.collections.generic;
using system.text;
using system.net;
using system.net.sockets;
namespace asyncserver
{
    public class asynctcpserver
    {
        public void start()
        {
            //创建套接字
            ipendpoint ipe = new ipendpoint(ipaddress.parse("127.0.0.1"), 6065);
            socket socket = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp);
            //绑定端口和ip
            socket.bind(ipe);
            //设置监听
            socket.listen(10);
            //连接客户端
            asyncaccept(socket);
        }
        /// <summary>
        /// 连接到客户端
        /// </summary>
        /// <param name="socket"></param>
        private void asyncaccept(socket socket)
        {
            socket.beginaccept(asyncresult =>
            {
                //获取客户端套接字
                socket client = socket.endaccept(asyncresult);
                console.writeline(string.format("客户端{0}请求连接...", client.remoteendpoint));
                asyncsend(client, "服务器收到连接请求");
                asyncsend(client, string.format("欢迎你{0}",client.remoteendpoint));
                asyncreveive(client);
            }, null);
        }
        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="client"></param>
        private void asyncreveive(socket socket)
        {
            byte[] data = new byte[1024];
            try
            {
                //开始接收消息
                socket.beginreceive(data, 0, data.length, socketflags.none,
                asyncresult =>
                {
                    int length = socket.endreceive(asyncresult);
                    console.writeline(string.format("客户端发送消息:{0}", encoding.utf8.getstring(data)));
                }, null);
            }
            catch (exception ex)
            {
                console.writeline(ex.message);
            }
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="client"></param>
        /// <param name="p"></param>
        private void asyncsend(socket client, string p)
        {
            if (client == null || p == string.empty) return;
            //数据转码
            byte[] data = new byte[1024];
            data = encoding.utf8.getbytes(p);
            try
            {
                //开始发送消息
                client.beginsend(data, 0, data.length, socketflags.none, asyncresult =>
                {
                    //完成消息发送
                    int length = client.endsend(asyncresult);
                    //输出消息
                    console.writeline(string.format("服务器发出消息:{0}", p));
                }, null);
            }
            catch (exception e)
            {
                console.writeline(e.message);
            }
        }
    }
}

客户端

基本流程

  • 创建套接字并保证与服务器的端口一致
  • 使用beginconnect()和endconnect()这组方法向服务端发送连接请求
  • 使用beginsend()/endsend和beginreceive()/endreceive()两组方法与服务端进行收发通信
  • 关闭套接字

代码示例

using system;
using system.collections.generic;
using system.text;
using system.net;
using system.net.sockets;
namespace asyncclient
{
    public class asynctcpclient
    {
        /// <summary>
        /// 连接到服务器
        /// </summary>
        public void asynconnect()
        {
            //端口及ip
            ipendpoint ipe = new ipendpoint(ipaddress.parse("127.0.0.1"), 6065);
            //创建套接字
            socket client = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp);
            //开始连接到服务器
            client.beginconnect(ipe, asyncresult =>
            {
                client.endconnect(asyncresult);
                //向服务器发送消息
                asynsend(client,"你好我是客户端");
                asynsend(client, "第一条消息");
                asynsend(client, "第二条消息");
                //接受消息
                asynrecive(client);
            }, null);
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="message"></param>
        public void asynsend(socket socket, string message)
        {
            if (socket == null || message == string.empty) return;
            //编码
            byte[] data = encoding.utf8.getbytes(message);
            try
            {
                socket.beginsend(data, 0, data.length, socketflags.none, asyncresult =>
                {
                    //完成发送消息
                    int length = socket.endsend(asyncresult);
                    console.writeline(string.format("客户端发送消息:{0}", message));
                }, null);
            }
            catch (exception ex)
            {
                console.writeline("异常信息:{0}", ex.message);
            }
        }
        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="socket"></param>
        public void asynrecive(socket socket)
        {
            byte[] data = new byte[1024];
            try
            {
                //开始接收数据
                socket.beginreceive(data, 0, data.length, socketflags.none,
                asyncresult =>
                {
                    int length = socket.endreceive(asyncresult);
                    console.writeline(string.format("收到服务器消息:{0}", encoding.utf8.getstring(data)));
                    asynrecive(socket);
                }, null);
            }
            catch (exception ex)
            {
                console.writeline("异常信息:", ex.message);
            }
        }
    }
}

从总体上来讲socket异步编程的逻辑性更加明确了,因为我们只需要为每一个过程写好回调函数就好了。那么这个示例的效果如何呢?我们来看看它的演示效果:

总结

和socket同步编程的案例相比,今天的这个案例可能只是对socket异步编程内容的一个简单应用,因为博主到现在为止都还没有写出一个可以进行交互聊天的程序来。在socket的异步编程中,服务端不需要为一个客户端单独创建一个线程来维护其连接,可是这样带来的一个问题就是博主不知道该如何实现一个多客户端的异步编程的实例。如果有朋友知道如何实现的话,还希望能够告诉我,毕竟学习就是一个相互促进的过程啊。好了,最后想说的是博主这段时间研究socket异步编程中关于异步方法调用的写法问题。我们知道socket异步编程中的方法是成对出现的,每一个方法都有一个回调函数,对于回调函数,这里有两种写法,以beginconnect方法为例:

m_socket.beginconnect(this.m_ipendpoint, 
        new asynccallback(this.connectcallback), 
        this.m_socket);//其中connectcallback是一个回调函数

或者

m_socket.beginconnect(this.m_ipendpoint,asyncresult=>
{
    //在这里添加更多代码
},null)

博主为什么要在这里说这两种写法呢,有两个原因:
* 第二种写法更为简洁,无需去构造容器传递socket和消息,因为它们都是局部变量。如果我们使用第一种方法,因为主函数和回调函数是两个不同的函数,因此如果想要共享变量就需要通过iasyncresult接口来访问容器中的值,这样显然增加了我们的工作量。
* 第二种写法更为优雅,这似乎是c#语言中某种高级语法,具体叫什么我忘了,反正在linq中经常看到这种写法的影子。

综合以上两个观点,博主还是建议大家使用第二种写法,博主打算有空的话将之前写的程序再重新写一遍,看看能不能找出代码中的问题。好了,今天的内容就是这样了,谢谢大家,希望大家喜欢!

到此这篇关于c#中socket通信编程的异步实现的文章就介绍到这了,更多相关c# socket通信编程内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

  • C#中的协变与逆变方式

    C#中的协变与逆变方式

    前言在 c# 中,协变(covariance)和逆变(contravariance)是两个重要的概念,主要用于处理泛型类型参数的可变性。这两个概念允许在泛型类型... [阅读全文]
  • C#中的命名空间详解(Namespace)

    C#中的命名空间详解(Namespace)

    前言命名空间(namespace)在于提供一种清晰、高效的方式,将一组名称与其他名称进行分隔,确保在不同命名空间里即便声明了相同名称的类,也不会引发冲突,恰似计... [阅读全文]
  • C#中的闭包使用详解

    C#中的闭包使用详解

    前言在 c# 中,闭包是一个强大的概念,它允许函数捕获外部变量并在函数外部访问这些变量。闭包在很多场景下都非常有用,比如在匿名函数、lambda 表达式和委托中... [阅读全文]
  • C#使用Dapper存取数据库详解

    dapper介绍dapper是的一个开源对象关系映射(orm)库.net和.net核心应用程序。该库允许开发人员快速轻松地访问数据库中的数据,而无需编写乏味的代码。dapper允许…

    2024年12月17日 编程语言
  • C#中的序列化与反序列化方式

    C#中的序列化与反序列化方式

    前言在 c# 编程中,序列化和反序列化是非常重要的概念。序列化是将对象转换为可以存储或传输的格式的过程,而反序列化则是将存储或传输的格式转换回对象的过程。这两个... [阅读全文]
  • C#中的Task使用方式

    C#中的Task使用方式

    前言在 c# 中,task代表一个异步操作。它允许你在不阻塞主线程的情况下执行耗时的操作,从而提高应用程序的响应性和性能。本教程将详细介绍 c# 中的task。... [阅读全文]

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com