`
pcajax
  • 浏览: 2157289 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

.net3.5下的Socket通信框架

 
阅读更多

.net3.5下的Socket通信框架

1:前言

写博客时间不短了但是一直不知道怎么开头。索性就开门见山吧。

这篇文章主要给大家介绍.net3.5下的Socket通信,主要从事件池,缓冲区以及协议三个方面给大家阐述。最后附上个我调试通过的项目。怎么说那?还是来个目录吧

A:通信框架图

B:通信流程图

C:简单介绍

D:源代码

先上通信框架图

 

首先声明这个源代码工程地址是http://www.codeproject.com/KB/IP/socketasynceventargssampl.aspx

其中用到的协议是http://www.cnblogs.com/JimmyZhang/archive/2008/09/16/1291854.html

简单说说各个类的作用

BufferManager:缓冲区

RequestHandler:协议

SocketAsyncEventArgsPool:事件池{可重复使用的套接字对象}

SocketClient:客户端

SocketListener:服务端

再上通信流程图

  

接下来就是本文的重点了,看看这些代码是如何工作的。

对于服务端

1:初始化一些对象,初始化的对象包括事件池和缓冲区。 

2:阻塞端口开始侦听客户端的链接。如果侦听到就readEventArgs.UserToken = e.AcceptSocket,因为我们在初始化事件池的时候只是简单的创建了SocketAsyncEventArgs对象并准备开始接收数据。在得到UserToken后就可以接收数据了。这里需要注意的是侦听到后不会等待接收过程结束才开始下一次侦听而是立即开始侦听{前提是如果事件池中有空闲对象的话}

3:接收过程。网上的例子由于没有考虑到协议所以客户端发送的数据可能会被截断。这里我们加上协议这一部分


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->private void ProcessReceive(SocketAsyncEventArgs e) {
            
//客户端是否关闭连接
            if (e.BytesTransferred > 0) {
                
if (e.SocketError == SocketError.Success) {
                    Socket s 
= e.UserToken as Socket;

                    Int32 bytesTransferred 
= e.BytesTransferred;
                    
//获取数据                    
                    String received = Encoding.ASCII.GetString(e.Buffer, e.Offset, bytesTransferred);

                    
//增加接收字节总量
                    Interlocked.Add(ref this.totalBytesRead, bytesTransferred);
                    
//Console.WriteLine("Received: \"{0}\". 服务共接受{1}字节.", received, this.totalBytesRead);

                    
                    
//Byte[] sendBuffer = Encoding.ASCII.GetBytes(received);

                    
// 获取实际的字符串
                    string[] msgArray = handler.GetActualString(received);
                    
// 清空缓存,避免脏读
                    Array.Clear(e.Buffer, e.Offset, bytesTransferred);        

                    
                    Boolean willRaiseEvent 
= false;

                    
//如果接收到完整的消息则发送回客户端否则继续接受
                    foreach (string m in msgArray) {
                        
byte[] temp = Encoding.ASCII.GetBytes(m);
                        e.SetBuffer(temp, 
0, temp.Length);
                        willRaiseEvent 
= s.SendAsync(e);
                    }

                    
if (!willRaiseEvent) {
                        
this.ProcessSend(e);
                    }

                }
                
else {
                    
this.CloseClientSocket(e);
                }
            }

 

4:接收完成的时候我们把SocketAsyncEventArgs对象放回事件池

服务端简单说两点。第一就是阻塞和就收都是异步的互不关联的,有的同学可能会这样


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->       private void StartAccept() {
           SocketAsyncEventArgs accept 
= this.readWritePool.Pop();
           
this.semaphoreAcceptedClients.WaitOne();
           listenSocket.AcceptAsync(accept);
       }

        
void accept_Completed(object sender, SocketAsyncEventArgs e)
        {

           StartAccept();

            var client 
= e.AcceptSocket;
            e.UserToken 
= e.AcceptSocket;

            e.Completed 
-= accept_Completed;
            e.Completed 
+= receive_Completed;

            var buffer 
= new byte[1024];
            e.SetBuffer(buffer, 
0, buffer.Length);

            client.ReceiveAsync(e);

 

这样写也行不过没有从代码级别把阻塞和接受分开。 我说的第二点是


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->                    Boolean willRaiseEvent = false;

                    
//如果接收到完整的消息则发送回客户端否则继续接受
                    foreach (string m in msgArray) {
                        
byte[] temp = Encoding.ASCII.GetBytes(m);
                        e.SetBuffer(temp, 
0, temp.Length);
                        willRaiseEvent 
= s.SendAsync(e);
                    }

                    
if (!willRaiseEvent) {
                        
this.ProcessSend(e);

 

也有同学这样写


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->                    Byte[] sendBuffer = Encoding.Unicode.GetBytes(received);

                    
s.Send(sendBuffer, sendBuffer.Length, SocketFlags.None);
                    
s.ReceiveAsync(e);                  
                                        

 

这样写的话就变成同步的了。效率不高{没有测试} 

对于客户端

1:异步连接服务器并用autoConnectEvent.WaitOne();等待连接完成。

2:发送数据


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public void Send(String message) {
            
if (this.connected) {

                
//将信息转化为协议
                message = String.Format("[length={0}]{1}", message.Length, message);
                Byte[] sendBuffer 
= Encoding.ASCII.GetBytes(message);

                SocketAsyncEventArgs completeArgs 
= new SocketAsyncEventArgs();
                completeArgs.SetBuffer(sendBuffer, 
0, sendBuffer.Length);
                completeArgs.UserToken 
= this.clientSocket;
                completeArgs.RemoteEndPoint 
= this.hostEndPoint;
                completeArgs.Completed 
+= new EventHandler<SocketAsyncEventArgs>(OnSend);

                clientSocket.SendAsync(completeArgs);

                
//等待本次发送接收时间{不必完成仅开始就好}
                AutoResetEvent.WaitAll(autoSendReceiveEvents);

                
//return Encoding.ASCII.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);
            }
            
else {
                
throw new SocketException((Int32)SocketError.NotConnected);
            }

 

这里我们把自己的协议加上。这里我把发送端改了一下,因为我们要在外部获取返回的数据。


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->        private void OnReceive(object sender, SocketAsyncEventArgs e) {
            
string msg = Encoding.ASCII.GetString(e.Buffer, 0, e.BytesTransferred);
            recInfo(msg);
            autoSendReceiveEvents[SendOperation].Set();

 

这里需要说的是AutoResetEvent.WaitAll(autoSendReceiveEvents)就是我们在发送完和启动接收后就开始下次发送而不必等接受完成。

最后送上客户端调用代码{服务端的没有改变}。 


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->        public static void Main(string[] args) {
            
try {
                String host 
= "192.168.70.100";
                Int32 port 
= 1232;
                Int16 iterations 
= 10;

                
using (SocketClient sa = new SocketClient(host, port)) {
                    sa.Connect();
                    sa.recInfo 
+= new SocketClient.GetReceive(InfoChange);

                    
for (Int32 i = 0; i < iterations; i++) {
                        
if (i % 2 == 0)
                            sa.Send(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
                        
else
                            sa.Send(
"222");
                    }
                    sa.Disconnect();

                    Console.WriteLine(
"Press any key to terminate the client process");
                    Console.Read();
                }
            }
            
catch (IndexOutOfRangeException) {
                Console.WriteLine(
"Usage: SocketAsyncClient <host> <port> [iterations]");
            }
            
catch (FormatException) {
                Console.WriteLine(
"Usage: SocketAsyncClient <host> <port> [iterations]." +
                    
"\r\n\t<host> Name of the host to connect." +
                    
"\r\n\t<port> Numeric value for the host listening TCP port." +
                    
"\r\n\t[iterations] Number of iterations to the host.");
            }
            
catch (Exception ex) {
                Console.WriteLine(
"ERROR: " + ex.Message);
            }
        }

        
static void InfoChange(string info) {
            Console.WriteLine(
"收到信息:{0}", info);

 

写在最后

本来想放上代码的。不过由于代码大部分来自于网上放上来有点。。。

如果哪位同学想要我调试过的就留个邮箱,我挨个给你们发。 

考虑到要的同学太多就放上源代码

源代码 

分享到:
评论

相关推荐

    ASP.NET 3.5从基础到项目实战 PPT

    ASP.NET 3.5是微软开发的一个用于构建Web应用程序的框架,它基于.NET Framework 3.5版本。这个PPT教程涵盖了从基础概念到实际项目实施的全面学习路径,旨在帮助开发者快速掌握ASP.NET 3.5的核心技术和实践技巧。 ...

    C#与.NET3.5高级程序设计源代码

    《C#与.NET3.5高级程序设计源代码》是一个重要的学习资源,它与《C#与.NET高级程序设计》这本书紧密相关,旨在帮助读者深入理解C#编程语言和.NET Framework 3.5的高级特性。这个源代码库包含了大量的示例程序和实践...

    C#利用Socket创建webservice

    【C#利用Socket创建Web服务】是通过C#编程语言基于.NET Framework 3.5或2.0版本,使用Socket类来实现的一种自定义通信协议的服务。Socket在计算机网络编程中扮演着重要的角色,它是应用层与传输层的接口,允许程序...

    socket开发框架

    "SocketEngine" 和 "SocketService" 可能是框架的核心组件,"SocketEngine" 可能是实现Socket通信的引擎,负责网络I/O操作和数据包的处理;而"SocketService"可能是服务端的抽象,提供启动、停止、管理Socket服务器...

    基于socket通信的销售管理系统设计与实现-毕设论文.doc

    通过本项目的开发,我们可以掌握 Socket 通信技术、C# 语言和 .NET Framework 框架的使用,并且提高自己的系统设计和开发能力。 参考文献 [1] 胡祖辉, 施佺. 基于 Socket 的 E-mail 信息平台的研究及其在教育管理...

    事件驱动的异步Socket

    在描述中提到的".Net3.5新增加的异步事件驱动Socket",实际上是指.NET Framework 3.5对异步Socket编程模型的增强,它提供了基于事件的异步模式,让开发者可以通过事件回调来处理网络事件,例如连接完成、数据接收或...

    基于socket通信的销售管理系统设计与实现大学论文.doc

    Web 开发新体验:ASP.NET 3.5 MVC 框架与实践[M]. 电子工业出版社, 2009. [9]黄忠成. 决战.NET .Net Framework 3.5 数据库开发圣典 ASP.NET 篇[M]. 电子工业出版社, 2008. [10] Laurence Moroney. Introducing ...

    superSocket

    SuperSocket.2010.NET35.sln, SuperSocket.2010.sln, SuperSocket.2012.NET40.sln, SuperSocket.2008.sln**:这些都是Visual Studio的解决方案文件,针对不同的.NET框架版本(如.NET Framework 3.5、4.0和2008、...

    C# Socket F3.5

    总的来说,C# Socket F3.5 框架旨在简化.NET Framework 3.5环境下C#的网络编程工作,提供了一套完整的解决方案,帮助开发者专注于业务逻辑,而不是底层的网络细节。通过充分利用这个框架,开发者能够更加高效地构建...

    SuperSocket官方下载1.6.6.zip

    SuperSocket是一款专为.NET平台设计的开源Socket服务器开发框架,它的出现极大地简化了网络通信服务的构建过程。标题中的"SuperSocket官方下载1.6.6.zip"表明我们正在讨论的是SuperSocket的1.6.6版本的官方下载包,...

    Socket异步传输数据实例(客户端服务端)

    总结来说,这个实例展示了如何使用`SocketAsyncEventArgs`进行高效异步的Socket通信,优化并发处理能力,并通过对象池和内存地址池来提升系统性能。这对于开发高并发、低延迟的网络应用,如在线游戏、实时数据交换等...

    对等ASP.NET状态服务器

    这些标签表明本项目涉及的技术栈主要基于微软的.NET框架,包括C#编程语言的不同版本(C#2.0和C#3.5),以及.NET Framework的多个版本(.NET2.0和.NET3.5)。此外,标签中的“ASP.NET”表示这是一个与Web开发相关的...

    CSR-Socket

    `CSR-Socket` 支持多种.NET框架版本,包括2.0、3.0、3.5和4.0。这表明该库具有良好的兼容性和长期支持,开发者可以根据项目需求选择合适的.NET版本,无需担心库的适配问题。同时,这也意味着`CSR-Socket` 遵循了.NET...

    NETCFv35.Messages.zh-CHS

    在.NET CF 3.5中,开发者可以利用丰富的类库进行网络通信编程,如System.Net命名空间下的Socket、HttpWebRequest、TcpClient等类,这些类提供了基础的网络通信功能,包括TCP/IP、HTTP协议的支持。对于进行网络数据...

    c# socket client

    SocketAsyncEventArgs是.NET Framework 3.5引入的一种异步操作模式,专门用于优化高并发的Socket通信。相比传统的Begin/End方法,它减少了对象创建和销毁的开销,提升了性能。在大量并发连接和数据传输的场景下,...

    Socket Server

    SocketAsyncEventArgs是.NET Framework 3.5引入的一个新特性,旨在提高多线程环境下的Socket操作性能。相比于传统的Begin/End方法,SocketAsyncEventArgs提供了更简洁的异步编程模型,并减少了线程上下文切换的开销...

    SuperSocket(1.5.1).Source

    这个框架支持多种平台,包括 .NET Framework 3.5 至 4.5,且至今仍在持续更新,确保与最新的开发环境和技术保持同步。 **核心特性** 1. **多线程模型**:SuperSocket 提供了灵活的多线程处理模型,可以根据业务...

    创建客户端-服务器应用-进行聊天

    在.NET 3.5中,System.Net命名空间下的Socket类是我们创建网络通信的关键,它支持TCP/IP协议,非常适合构建稳定的聊天应用。 Win32和Win64指的是Windows API,它们提供底层操作系统接口,用于处理窗口、消息和系统...

    C#和VB.NET的SNTP客户端

    标签中提及的".NET2.0, .NET3.0, .NET3.5"表明这些实现可能兼容这些版本的.NET框架,而"VB8, VB9"指的是Visual Basic .NET的2005(VB8)和2008(VB9)版本。"C#3.0"则对应C#语言的第三个主要版本,引入了如lambda...

    毕业文论:远程无线粮库实时监控管理系统的设计与实现.docx

    综上所述,本文通过结合Web Service、.NET Framework 3.5、SQL Server和Socket通信等技术,成功设计并实现了一个远程无线粮库实时监控管理系统,不仅提升了粮库管理的效率,也为粮食安全提供了有力保障。同时,系统...

Global site tag (gtag.js) - Google Analytics