Socket通讯服务端

本文内容:利用SocketAsyncEventArgs实现的echo服务端。主要分为两部分:1、实现的基本步骤;2、关于各个类的功能解释;3、实现各类的代码。

一、在服务端,使用SocketAsyncEventArgs的基本步骤:

     1.设置一个buffer池,以供SocketAsynceEventArgs接收和发送数据的缓冲区。

     2.添加一个object类,为SocketAsyncEventArgs的UserToken对象作准备。

     3.添加一个双通道(发送/接收)SocketAsyncEventArgs的对象DuplexSocketAsync。其为SocketAsyncEventArgs添加Completed事件,UserToken属性。

     4.添加一个DuplexSocketAsync池,其目的是:在服务的开始阶段进行初始化,以节约时间,提高效率。

     5.Socket接收一个SocketAsyncEventArgs对象。或者为了提高并发处理能力,可以为SocketAsyncEventArgs对象建立一个池。用来接收客户端。

    6.调用SocketAsyncEventArgs的AcceptAsync方法启动异步接收客户端。

    7.将接收的客户端赋给DuplexSocketAsync池中的对象。

    8.将Socket接收的SocketAsyncEventArgs对象循环使用,接收下一个客户端的连接。

二、涉及的主要类介绍:

    BufferManager.cs:主要是对SocketAsyncEventArgs的接收/发送数据缓冲区的设置,这样尽量避免内存碎片。

    AsyncUserToken.cs:主要是记载SocketAsyncEventArgs的其它信息,例如接收时间信息、信息的大小等。

    DuplexSocketAsync.cs:主要是建立两个SocketAsyncEvnetArgs分别用于发送信息和接收信息。实现对一客户端之间的通信。

    DuplexSocketPool.cs:主要是为DuplexSocketAsync建立一个池,用于提高效率。

    SocketMain.cs:主要是通过Socket ,启动侦听客户端。

三、各个类的代码

 BufferManager.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Net;
6 using System.Net.Sockets;
7 namespace y.AircraftCarriers.SocketOperation
8 {
9 class BufferManager
10 {
11 int bufferSize = 0;
12 int totalSize = 0;
13 byte[] totalByte = null;
14 Stack<int> offsetStack = null;
15 int offset = 0;
16
17 public int BufferSize
18 {
19 get { return bufferSize; }
20 }
21
22 public BufferManager(int totalSize, int bufferSize)
23 {
24 this.totalSize = totalSize;
25 this.bufferSize = bufferSize;
26 totalByte = new byte[totalSize];
27 offsetStack = new Stack<int>(3000);
28 }
29
30 public bool SetBuffer(SocketAsyncEventArgs args)
31 {
32 if (offsetStack.Count > 0)
33 {
34 args.SetBuffer(totalByte, offsetStack.Pop(), bufferSize);
35 return true;
36 }
37 else
38 {
39 if (totalSize - offset >= bufferSize)
40 {
41 args.SetBuffer(totalByte, offset, bufferSize);
42 offset += bufferSize;
43 return true;
44 }
45 else
46 {
47 return false;
48 }
49 }
50 }
51
52 public void FreeBuffer(SocketAsyncEventArgs args)
53 {
54 offsetStack.Push(args.Offset);
55 args.SetBuffer(null, 0, 0);
56 }
57
58
59 }
60 }

AsyncUserToken.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using System.Net;
7 using System.Net.Sockets;
8 namespace y.AircraftCarriers.SocketOperation
9 {
10 class AsyncUserToken
11 {
12
13 }
14 }

DuplexSocketAsync.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using System.Net;
7 using System.Net.Sockets;
8 using System.Threading;
9 namespace y.AircraftCarriers.SocketOperation
10 {
11
12 class DuplexSocketAsync
13 {
14 public SocketAsyncEventArgs SendSocketAsync = null;
15 private AsyncUserToken SendUserToken = null;
16 public SocketAsyncEventArgs ReceiveSocketAsync = null;
17 private AsyncUserToken ReceiveUserToken = null;
18 private int bufferSize = 0;
19
20 public DuplexSocketAsync(int bufferSize)
21 {
22 this.bufferSize = bufferSize;
23 SendSocketAsync = new SocketAsyncEventArgs();
24 SendUserToken = new AsyncUserToken ();
25
26 ReceiveSocketAsync = new SocketAsyncEventArgs();
27 ReceiveUserToken = new AsyncUserToken();
28 Initialize();
29 }
30 public void Initialize()
31 {
32 SendSocketAsync.UserToken = SendUserToken;
33 SendSocketAsync.Completed +=new EventHandler<SocketAsyncEventArgs>(IO_Completed);
34
35 ReceiveSocketAsync.UserToken = ReceiveSocketAsync;
36 ReceiveSocketAsync.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
37 }
38
39 private void IO_Completed(object sender, SocketAsyncEventArgs args)
40 {
41 switch (args.LastOperation)
42 {
43 case SocketAsyncOperation.Receive:
44 ProcessReceive(args);
45 break;
46 case SocketAsyncOperation.Send:
47 ProcessSend(args);
48 break;
49 case SocketAsyncOperation.Disconnect:
50 ProcessClose();
51 break;
52 default:
53 break;
54 }
55 }
56
57
58 private void ProcessReceive(SocketAsyncEventArgs args)
59 {
60 if (args.BytesTransferred > 0 && args.SocketError == SocketError.Success)
61 {
62 string msg = Encoding.UTF8.GetString(args.Buffer, args.Offset, args.BytesTransferred);
63 Console.WriteLine("[{0}]\r\n[Receive]:{1}", DateTime.Now.ToString(), msg);
64 bool raiseEvent = args.AcceptSocket.ReceiveAsync(args);
65 if (!raiseEvent)
66 {
67 ProcessReceive(args);
68 }
69 }
70 else
71 {
72 args.AcceptSocket.Shutdown(SocketShutdown.Receive);
73 ProcessClose();
74 }
75 }
76 public void StartReceive(SocketAsyncEventArgs args)
77 {
78 if (args.AcceptSocket != null)
79 {
80 bool raiseEvent = args.AcceptSocket.ReceiveAsync(args);
81 if (!raiseEvent)
82 {
83 ProcessReceive(args);
84 }
85 }
86 }
87 private void ProcessSend(SocketAsyncEventArgs args)
88 {
89 if (args.SocketError != SocketError.Success)
90 {
91 args.AcceptSocket.Shutdown(SocketShutdown.Send);
92 ProcessClose();
93 }
94 }
95 private void ProcessClose()
96 {
97 SendSocketAsync.AcceptSocket = null;
98 ReceiveSocketAsync.AcceptSocket = null;
99 Interlocked.Decrement(ref Parameter.onlineConnection);
100 Console.WriteLine("onlineConnection:{0}", Parameter.onlineConnection);
101 Parameter.FreeDuplexSocketAsyncPool.Push(this);
102 Console.WriteLine("Pool Count:{0}", Parameter.FreeDuplexSocketAsyncPool.Count);
103
104 }
105 public void SendData(SocketAsyncEventArgs args,string msg)
106 {
107 byte[] msgByte = Encoding.UTF8.GetBytes(msg);
108 int len= msgByte.Length;
109 int msgLen=len;
110 while(len>this.bufferSize)
111 {
112 args.SetBuffer(args.Buffer, args.Offset, bufferSize);
113 Array.Copy(msgByte, msgLen - len, args.Buffer, args.Offset, bufferSize);
114 args.AcceptSocket.SendAsync(args);
115 len -= this.bufferSize;
116 }
117 args.SetBuffer(args.Buffer, args.Offset, len);
118 Array.Copy(msgByte, msgLen - len, args.Buffer, args.Offset, len);
119 args.AcceptSocket.SendAsync(args);
120
121 }
122
123 public void SetSocket(Socket socket)
124 {
125 ReceiveSocketAsync.AcceptSocket = socket;
126
127 SendSocketAsync.AcceptSocket = socket;
128 }
129 }
130 }

DuplexSocketPool.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using System.Net;
7 using System.Net.Sockets;
8 namespace y.AircraftCarriers.SocketOperation
9 {
10 class DuplexSocketPool
11 {
12 private Stack<DuplexSocketAsync> duplexSocketPool = null;
13 private int capacity = 0;
14 private int bufferSize = 0;
15 private BufferManager bufferManager = null;
16 private object objSyncRoot = new object();
17
18 public DuplexSocketPool(int capacity,int bufferSize)
19 {
20 this.capacity = capacity;
21 this.bufferSize = bufferSize;
22 bufferManager = new BufferManager(this.capacity * 2 * this.bufferSize, bufferSize);
23 duplexSocketPool = new Stack<DuplexSocketAsync>(capacity);
24 Initialize();
25 }
26 private void Initialize()
27 {
28 for (int i = 0; i < capacity; ++i)
29 {
30 DuplexSocketAsync duplexSocket = new DuplexSocketAsync(bufferManager.BufferSize);
31 bufferManager.SetBuffer(duplexSocket.ReceiveSocketAsync);
32 bufferManager.SetBuffer(duplexSocket.SendSocketAsync);
33 this.Push(duplexSocket);
34 }
35 }
36 public void Push(DuplexSocketAsync duplexSocket)
37 {
38 lock (objSyncRoot)
39 {
40 duplexSocketPool.Push(duplexSocket);
41 }
42 }
43
44 public DuplexSocketAsync Pop()
45 {
46 lock (objSyncRoot)
47 {
48 if (duplexSocketPool.Count > 0)
49 {
50 return duplexSocketPool.Pop();
51 }
52 else
53 {
54 return null;
55 }
56 }
57 }
58
59 public int Count
60 {
61 get { return duplexSocketPool.Count; }
62 }
63 }
64 }

Parameter.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace y.AircraftCarriers.SocketOperation
7 {
8 class Parameter
9 {
10 public static int onlineConnection = 0;
11 public static DuplexSocketPool FreeDuplexSocketAsyncPool = null;
12 }
13 }

SocketMain.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using System.Net;
7 using System.Net.Sockets;
8 using System.Threading;
9 namespace y.AircraftCarriers.SocketOperation
10 {
11 class SocketMain
12 {
13 Socket socketListen = null;
14 IPEndPoint iep = null;
15 ManualResetEvent done = new ManualResetEvent(false);
16 //DuplexSocketPool duplexSocketPool = null;
17
18 public SocketMain(IPEndPoint iep,int bufferSize,int maxConnection)
19 {
20 socketListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
21 this.iep = iep;
22 Parameter.FreeDuplexSocketAsyncPool = new DuplexSocketPool(maxConnection, bufferSize);
23 }
24
25 public void StartListen()
26 {
27 socketListen.Bind(iep);
28 socketListen.Listen(10000);
29
30 StartAccept(null);
31
32 }
33
34 private void StartAccept(SocketAsyncEventArgs acceptArgs)
35 {
36 if (acceptArgs == null)
37 {
38 acceptArgs = new SocketAsyncEventArgs();
39 acceptArgs.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptArgs_Completed);
40 }
41 else
42 {
43 acceptArgs.AcceptSocket = null;
44 }
45 bool raiseEvent = socketListen.AcceptAsync(acceptArgs);
46 if (!raiseEvent)
47 {
48 ProcessAccept(acceptArgs);
49 }
50 done.WaitOne();
51 }
52 private void AcceptArgs_Completed(object sender,SocketAsyncEventArgs args)
53 {
54 ProcessAccept(args);
55 }
56 private void ProcessAccept(SocketAsyncEventArgs args)
57 {
58 Interlocked.Increment(ref Parameter.onlineConnection);
59 Console.WriteLine("onlineConnection:{0}", Parameter.onlineConnection);
60 DuplexSocketAsync duplexSocket = Parameter.FreeDuplexSocketAsyncPool.Pop();
61 Console.WriteLine("Pool Count:{0}", Parameter.FreeDuplexSocketAsyncPool.Count);
62
63 duplexSocket.SetSocket(args.AcceptSocket);
64 args.AcceptSocket = null;
65
66 duplexSocket.SendData(duplexSocket.SendSocketAsync, "This from Server");
67 duplexSocket.ReceiveSocketAsync.AcceptSocket.ReceiveAsync(duplexSocket.ReceiveSocketAsync);
68 done.Set();
69 StartAccept(args);
70
71 }
72 }
73 }

App.config

ContractedBlock.gif ExpandedBlockStart.gif View Code
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <appSettings>
4 <add key="IP" value="127.0.0.1"/>
5 <add key="Port" value="2345"/>
6 <add key="BufferSize" value="1024"/>
7 <add key="MaxConnection" value="30000"/>
8 </appSettings>
9 </configuration>

Program.cs

ContractedBlock.gif ExpandedBlockStart.gif View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using y.AircraftCarriers.SocketOperation;
7 using System.Net;
8 using System.Net.Sockets;
9 using System.Configuration;
10 namespace y.AircraftCarriers
11 {
12 class Program
13 {
14 static void Main(string[] args)
15 {
16 Console.Title = "SocketAsyncEventArgs Server";
17 Console.WriteLine("Press any key to exit......\r\n");
18 string IP = ConfigurationManager.AppSettings["IP"];
19 int Port = int.Parse(ConfigurationManager.AppSettings["Port"]);
20 int BufferSize = int.Parse(ConfigurationManager.AppSettings["BufferSize"]);
21 int MaxConnection = int.Parse(ConfigurationManager.AppSettings["MaxConnection"]);
22 IPEndPoint iep= new IPEndPoint(IPAddress.Parse(IP),Port);
23 SocketMain socketMain = new SocketMain(iep, BufferSize,MaxConnection);
24
25 socketMain.StartListen();
26 Console.ReadKey();
27 }
28 }
29 }

参考文献:

http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx

转载于:https://www.cnblogs.com/xyz168/archive/2011/08/10/2133486.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值