详解C# Socket异步通信实例

时间:2022-07-01 02:39:50

TCPServer 

1、使用的通讯通道:socket

2、用到的基本功能:

①Bind,

②Listen,

③BeginAccept

④EndAccept

⑤BeginReceive 

⑥EndReceive

3、函数参数说明

?
1
2
3
Socket listener = new Socket(AddressFamily.InterNetwork,
 
     SocketType.Stream, ProtocolType.Tcp);

新建socket所使用的参数均为系统预定义的量,直接选取使用。

?
1
listener.Bind(localEndPoint);

localEndPoint 表示一个定义完整的终端,包括IP和端口信息。

?
1
2
3
4
5
//new IPEndPoint(IPAddress,port)
 
//IPAdress.Parse("192.168.1.3")
 
listener.Listen(100);

监听

?
1
2
3
4
5
listener.BeginAccept(
 
        new AsyncCallback(AcceptCallback),
 
        listener);

AsyncCallback(AcceptCallback),一旦连接上后的回调函数为AcceptCallback。当系统调用这个函数时,自动赋予的输入参数为IAsyncResoult类型变量ar。

 listener,连接行为的容器。

?
1
Socket handler = listener.EndAccept(ar);

完成连接,返回此时的socket通道。

?
1
2
3
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
 
      new AsyncCallback(ReadCallback), state);

接收的字节,0,字节长度,0,接收时调用的回调函数,接收行为的容器。

========

容器的结构类型为:

?
1
2
3
4
5
6
7
8
9
10
11
public class StateObject
{
  // Client socket.
  public Socket workSocket = null;
  // Size of receive buffer.
  public const int BufferSize = 1024;
  // Receive buffer.
  public byte[] buffer = new byte[BufferSize];
  // Received data string.
  public StringBuilder sb = new StringBuilder();
}

容器至少为一个socket类型。

===============

?
1
2
3
// Read data from the client socket.
 
   int bytesRead = handler.EndReceive(ar);

完成一次连接。数据存储在state.buffer里,bytesRead为读取的长度。

?
1
2
3
handler.BeginSend(byteData, 0, byteData.Length, 0,
 
      new AsyncCallback(SendCallback), handler);

发送数据byteData,回调函数SendCallback。容器handler

?
1
int bytesSent = handler.EndSend(ar);

发送完毕,bytesSent发送字节数。

4 程序结构

主程序:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  byte[] bytes = new Byte[1024];
  IPAddress ipAddress = IPAddress.Parse("192.168.1.104");
  IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
 
  // 生成一个TCP的socket
  Socket listener = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Tcp);
 
  listener.Bind(localEndPoint);
  listener.Listen(100);
 
  while (true)
  {
 
    // Set the event to nonsignaled state.
    allDone.Reset();
 
    //开启异步监听socket
    Console.WriteLine("Waiting for a connection");
    listener.BeginAccept(
         new AsyncCallback(AcceptCallback),
         listener);
 
    // 让程序等待,直到连接任务完成。在AcceptCallback里的适当位置放置allDone.Set()语句.
    allDone.WaitOne();
    }
 
Console.WriteLine("\nPress ENTER to continue");
Console.Read();

连接行为回调函数AcceptCallback:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void AcceptCallback(IAsyncResult ar)
 
{
 
  //添加此命令,让主线程继续.
 
  allDone.Set();
 
  // 获取客户请求的socket
 
  Socket listener = (Socket)ar.AsyncState;
 
  Socket handler = listener.EndAccept(ar);
 
  // 造一个容器,并用于接收命令.
 
  StateObject state = new StateObject();
 
  state.workSocket = handler;
 
  handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
 
    new AsyncCallback(ReadCallback), state);
 
}

读取行为的回调函数ReadCallback:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public static void ReadCallback(IAsyncResult ar)
 
{
 
  String content = String.Empty;
 
  // 从异步state对象中获取state和socket对象.
 
  StateObject state = (StateObject)ar.AsyncState;
 
  Socket handler = state.workSocket;
 
  // 从客户socket读取数据.
 
  int bytesRead = handler.EndReceive(ar);
 
  if (bytesRead > 0)
 
  {
 
    // 如果接收到数据,则存起来
 
    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
 
    // 检查是否有结束标记,如果没有则继续读取
 
    content = state.sb.ToString();
 
    if (content.IndexOf("<EOF>") > -1)
 
    {
 
      //所有数据读取完毕.
 
      Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
 
        content.Length, content);
 
      // 给客户端响应.
 
      Send(handler, content);
 
    }
 
    else
 
    {
 
      // 接收未完成,继续接收.
 
      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
 
      new AsyncCallback(ReadCallback), state);
 
    }
 
  }
 
}

发送消息给客户端:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private static void Send(Socket handler, String data)
 
  {
 
    // 消息格式转换.
 
    byte[] byteData = Encoding.ASCII.GetBytes(data);
 
    // 开始发送数据给远程目标.
 
    handler.BeginSend(byteData, 0, byteData.Length, 0,
 
      new AsyncCallback(SendCallback), handler);
 
  }
 
private static void SendCallback(IAsyncResult ar)
 
  {
 
   
 
      // 从state对象获取socket.
 
      Socket handler = (Socket)ar.AsyncState;
 
      //完成数据发送
 
      int bytesSent = handler.EndSend(ar);
 
      Console.WriteLine("Sent {0} bytes to client.", bytesSent);
 
      handler.Shutdown(SocketShutdown.Both);
 
      handler.Close();
 
  }

在各种行为的回调函数中,所对应的socket都从输入参数的AsyncState属性获得。使用(Socket)或者(StateObject)进行强制转换。BeginReceive函数使用的容器为state,因为它需要存放传送的数据。

而其余接收或发送函数的容器为socket也可。

完整代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using System;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System.Threading;
 
 // State object for reading client data asynchronously
 public class StateObject
 {
  // Client socket.
  public Socket workSocket = null;
  // Size of receive buffer.
  public const int BufferSize = ;
  // Receive buffer.
  public byte[] buffer = new byte[BufferSize];
  // Received data string.
  public StringBuilder sb = new StringBuilder();
}
 
public class AsynchronousSocketListener
{
  // Thread signal.
  public static ManualResetEvent allDone = new ManualResetEvent(false);
 
  public AsynchronousSocketListener()
  {
  }
 
  public static void StartListening()
  {
    // Data buffer for incoming data.
    byte[] bytes = new Byte[];
 
    // Establish the local endpoint for the socket.
    // The DNS name of the computer
    // running the listener is "host.contoso.com".
    //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
    IPAddress ipAddress = IPAddress.Parse("...");
 
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, );
 
    // Create a TCP/IP socket.
    Socket listener = new Socket(AddressFamily.InterNetwork,
      SocketType.Stream, ProtocolType.Tcp);
 
    // Bind the socket to the local endpoint and listen for incoming connections.
    try
    {
      listener.Bind(localEndPoint);
      listener.Listen();
      while (true)
      {
        // Set the event to nonsignaled state.
        allDone.Reset();
 
        // Start an asynchronous socket to listen for connections.
        Console.WriteLine("Waiting for a connection");
        listener.BeginAccept(
          new AsyncCallback(AcceptCallback),
          listener);
 
        // Wait until a connection is made before continuing.
        allDone.WaitOne();
      }
    }
    catch (Exception e)
    {
      Console.WriteLine(e.ToString());
    }
 
    Console.WriteLine("\nPress ENTER to continue");
    Console.Read();
  }
 
  public static void AcceptCallback(IAsyncResult ar)
  {
    // Signal the main thread to continue.
    allDone.Set();
 
    // Get the socket that handles the client request.
    Socket listener = (Socket)ar.AsyncState;
    Socket handler = listener.EndAccept(ar);
 
    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive(state.buffer, , StateObject.BufferSize, , new AsyncCallback(ReadCallback), state);
  }
 
  public static void ReadCallback(IAsyncResult ar)
  {
    String content = String.Empty;
   
    // Retrieve the state object and the handler socket
    // from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;
 
    // Read data from the client socket.
    int bytesRead = handler.EndReceive(ar);
 
    if (bytesRead > )
    {
      // There might be more data, so store the data received so far.
      state.sb.Append(Encoding.ASCII.GetString(
        state.buffer, , bytesRead));
 
      // Check for end-of-file tag. If it is not there, read
      // more data.
      content = state.sb.ToString();
      if (content.IndexOf("<EOF>") > -)
      {
        // All the data has been read from the
        // client. Display it on the console.
        Console.WriteLine("Read {} bytes from socket. \n Data : {}",content.Length, content);
 
        // Echo the data back to the client.
        Send(handler, content);
      }
      else
      {
        // Not all data received. Get more.
        handler.BeginReceive(state.buffer, , StateObject.BufferSize, , new AsyncCallback(ReadCallback), state);
      }
    }
  }
 
  private static void Send(Socket handler, String data)
  {
    // Convert the string data to byte data using ASCII encoding.
    byte[] byteData = Encoding.ASCII.GetBytes(data);
 
    // Begin sending the data to the remote device.
    handler.BeginSend(byteData, , byteData.Length, ,
      new AsyncCallback(SendCallback), handler);
  }
 
 
 
  private static void SendCallback(IAsyncResult ar)
 
  {
    try
    {
      // Retrieve the socket from the state object.
      Socket handler = (Socket)ar.AsyncState;
 
      // Complete sending the data to the remote device.
      int bytesSent = handler.EndSend(ar);
      Console.WriteLine("Sent {} bytes to client.", bytesSent);
      handler.Shutdown(SocketShutdown.Both);
      handler.Close();
    }
 
    catch (Exception e)
 
    {
      Console.WriteLine(e.ToString());
    }
  }
 
  public static int Main(String[] args)
 
  {
    StartListening();
    return ;
  }
 
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://www.cnblogs.com/kingmoon/archive/2011/04/29/2032452.html