.NET Socket开发(2) 异步Socket

在基于.NET的网络服务端的开发中,我们用到和听到的最多的恐怕就是异步Socket了。异步Socket的性能比同步高出很多,但是编写代码比较复杂。因此异步Socket也是网络上讨论比较多的话题。

今天,我们就来讨论一下如何用异步Socket开发网络应用。在此之前我们先讨论两个问题。

一、异步Socket是如何工作的:

那异步Socket是如何工作的呢?我以接收一条消息来说明这个问题。首先,程序向系统投递一个接收数据的请求,并为其指定一个数据缓冲区和回调函数,回调函数用来指示当数据到达后将如何处理,然后我们的程序继续执行下去,当有数据到达的时候,系统将数据读入缓冲区,并执行回调函数,处理这条消息。我们并不需要关心这条消息何时到达。

二、什么情况下我们用异步Socket:

有些人认为,异步Socket的性能比同步Socket的性能高很多,应该在各种环境下都用异步Socket,其实不然。在某些环境下面。异步反到比同步的性能低,那么在哪些情况下会这样呢?

1、 客户端Socket。

2、 服务端连接数比较少。

3、 连接数很多,但都是短连接。

在这些环境下,我们用同步Socket不但可以简化代码,而且性能并不会比异步Socket低。但在服务端连接比较多而且是长连接的情况下,我们就要使用异步Socket。

现在我们来看看如何用异步Socket编程。

  服务端:

ExpandedBlockStart.gif 代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading;
using  System.Net;
using  System.Net.Sockets;

namespace  CutImage
{
    
public   class  MySocket
    {
        Socket _server;
        
public  MySocket()
        {        
            _server 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _server.Bind(
new  IPEndPoint(IPAddress.Any, 8808 ));
            _server.Listen(
100 );

            Thread th 
=   new  Thread( new  ThreadStart(WriteConnetion));
            th.Start();
        }
        
///   <summary>
        
///  等待客户端连接的方法
        
///   </summary>
         void  WriteConnetion()
        {
            
while ( true )
            {
                Socket s 
=  _server.Accept();
                User user 
=   new  User();
                user.Userid 
= Guid.NewGuid().ToString();
                user.mysocket 
=  s;
                s.BeginReceive(user.msg, 
0 , user.msg.Length, SocketFlags.None,  new  AsyncCallback(Recivecallback),user); // 向系统投递一个接受信息的请求 Recivecallback为回调函数
            }
        }
        
///   <summary>
        
///  接受信息的回调函数
        
///   </summary>
        
///   <param name="ar"></param>
          void  Recivecallback(IAsyncResult ar)
        {
            User user 
=  (User)ar.AsyncState;
            Socket _customersocket
= user.mysocket;
            
int  recivecount = 0 ;
            
try
            {
                 recivecount 
=  _customersocket.EndReceive(ar);
            }
            
catch  (SocketException) // 连接断开
            {
                Close(user);
            }
catch
            {

            }
            
if (recivecount > 0 )
            {
                
byte [] buffer  =   new   byte [recivecount]; // 收到的信息
                Buffer.BlockCopy(user.msg,  0 , buffer,  0 , recivecount);
                GetMsg(user, buffer);
// 这个函数用来处理接收到的信息
                 try
                {
                    user.mysocket.BeginReceive(user.msg, 
0 , user.msg.Length, SocketFlags.None,  new  AsyncCallback(Recivecallback), user);
                }
                
catch  (SocketException)
                {
                    Close(user);
                }
                
catch
                {

                }
            }
            
else // 如果接收到0字节的数据说明客户端关闭了Socket,那我们也要关闭Socket
            {
                Close(user);
            }
          
        }
        
///   <summary>
        
///  断开连接
        
///   </summary>
        
///   <param name="u"></param>
         void  Close(User u)
        {
            Console.WriteLine(u.Userid 
+   " 连接断开 " );
            
return ;
        }
        
///   <summary>
        
///  收到信息的处理函数
        
///   </summary>
        
///   <param name="u"></param>
        
///   <param name="msg"></param>
         void  GetMsg(User u, byte [] msg)
        {
            
string  _msg = Encoding.UTF8.GetString(msg);
            Console.WriteLine(u.Userid 
+   " 收到数据: "   +  _msg);
            SendMsg(u, msg);
        }
        
///   <summary>
        
///  发送信息
        
///   </summary>
        
///   <param name="user"></param>
        
///   <param name="msg"></param>
         void  SendMsg(User user, byte [] msg)
        {
            
try
            {
                user.mysocket.BeginSend(msg, 
0 , msg.Length, SocketFlags.None,  new  AsyncCallback(Sendcallback), user);
                
string  str = Encoding.UTF8.GetString(msg);
                Console.WriteLine(user.Userid 
+   " 发送数据: "   +  str);
            }
            
catch  (SocketException)
            {
                Close(user);
            } 
        }
        
///   <summary>
        
///  发送信息的回调
        
///   </summary>
        
///   <param name="ar"></param>
         void  Sendcallback(IAsyncResult ar)
        {
           
 User u  =  (User)ar.AsyncState;
            
try
            {
                u.mysocket.EndSend(ar);
            }
            
catch  (System.Exception ex)
            {
                
            }
        }
    }
}

 

客户端:

 

ExpandedBlockStart.gif 代码
            client  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(
" 127.0.0.1 " 8808 );
            
for ( int  i = 1 ;i < 51 ;i ++ )
            {
                
// 发送信息
                 byte [] buffer  =  Encoding.UTF8.GetBytes( " Login| " + i);
                client.Send(buffer, 
0 , buffer.Length, SocketFlags.None);
                
// 接受信息
                 byte [] buffer1 = new   byte [ 1024 ];
                client.Receive(buffer1, 
0 , buffer1.Length, SocketFlags.None);
                
string  str = Encoding.UTF8.GetString(buffer);
                Console.WriteLine(
" 收到服务端返回信息: " + str);
            }

 

 

 

转载于:https://www.cnblogs.com/bobofsj11/archive/2010/02/24/1672874.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值