C#实现异步socket通信

C#异步socket通信

我们在开发网络通信软件的时候,都需要实现异步的通信,有效的提高通信效率,下面来介绍下C#中异步socket通信的实现方式。

服务器端处理方式

首先定义一个用于函数回调传递的参数实体类:

1
2
3
4
5
6
7
8
9
10
11
public class StateObject
{
// 保存的socket连接
public Socket workSocket = null;
// 接收的数据大小    
public const int BufferSize = 1024;
// 接收的数据缓冲区    
public byte[] buffer = new byte[BufferSize];
        // 其他一些自定义数据字段
public int num;
}

获取本地网络IP地址:

1
2
3
4
5
6
7
8
9
10
string name = Dns.GetHostName();
IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
foreach (IPAddress ipa in ipadrlist)
{
if (ipa.AddressFamily == AddressFamily.InterNetwork)
{
ServerIP1.Text = ipa.ToString();
break;
}
}

接收到消息后使用委托函数更新UI界面,避免出现跨线程调用UI控件时的错误:

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
/// <summary>
/// 更新界面状态信息委托回调事件
/// </summary>
/// <param name="str"></param>
public delegate void ShowStatusCallBack(String str);
/// <summary>
/// 更新界面状态信息
/// </summary>
/// <param name="str"></param>
public void ShowStatus(string str)
{
if (this.InvokeRequired)
{
ShowStatusCallBack d = new ShowStatusCallBack(ShowStatus);
this.Invoke(d, new object[] { str });
}
else
{
textBoxMessage.Text += str + "\r\n";
textBoxMessage.SelectionStart = textBoxMessage.Text.Length;
textBoxMessage.ScrollToCaret();
 
if(textBoxMessage.Text.Length > 10000)
{
textBoxMessage.Clear();
}
}
}

开启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
public void StartServer(int num, string ip, string port)
{
IPAddress address = IPAddress.Parse(ip.Trim());
int portNum = int.Parse(port.Trim());
IPEndPoint endPoint = new IPEndPoint(address, portNum);
 
try
{
// 创建负责监听的套接字,注意其中的参数;  
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
listener.Bind(endPoint);
// 设置监听队列的长度;  
listener.Listen(10);
 
StateObject stateObject = new StateObject();
stateObject.workSocket = listener;
stateObject.num = num;
// Set the event to nonsignaled state.    
listener.BeginAccept(new AsyncCallback(AcceptCallback), stateObject);
textBoxMessage.Text += "服务器" + num.ToString() + "已开启,等待连接。。。。。\r\n";
}
catch (Exception ex)
{
ShowStatus(ex.Message);
}
}

客户端连接异步回调函数,保存连接成功的客户端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
public void AcceptCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket.EndAccept(ar);
 
IPEndPoint remoteEndPoint;
remoteEndPoint = (IPEndPoint)client.RemoteEndPoint;
 
ShowStatus("客户端已连接!" + remoteEndPoint.Address.ToString() + ":" + remoteEndPoint.Port.ToString());
 
StateObject clientState = new StateObject();
clientState.num = state.num;
clientState.workSocket = client;
 
client.BeginReceive(clientState.buffer, 0, clientState.buffer.Length, 0, new AsyncCallback(ReadCallback), clientState);
 
switch (state.num)
{
//自定义处理
}
 
//继续监听客户端连接
state.workSocket.BeginAccept(new AsyncCallback(AcceptCallback), state);
}
catch (Exception ex)
{
ShowStatus(ex.Message);
}
}

异步接收数据回调函数,接收完毕数据后,继续开启等待接收新的数据:

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 void ReadCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
 
// Read data from the client socket.    
int bytesRead = state.workSocket.EndReceive(ar);
if (bytesRead > 0)
{
content = ByteToString(state.buffer, bytesRead);
ShowStatus("服务器--" + state.num + "-- " + content);
//转发
Send(state, bytesRead);
 
Array.Clear(state.buffer, 0, state.buffer.Length);
 
state.workSocket.BeginReceive(state.buffer, 0, state.buffer.Length, 0, new AsyncCallback(ReadCallback), state);
}
 
} catch (Exception ex)
{
ShowStatus(ex.Message);
}
}

发送数据,同样使用异步回调函数来确保数据发送完毕,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
private 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);
ShowStatus("已发送数据大小:" + bytesSent.ToString());
}
catch (Exception e)
{
ShowStatus(e.Message);
}
}

客户端连接服务器

客户端连接服务器,同样使用连接回调方式来连接服务器:

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
public void ConnectServer(int num, string ip,string port)
{
try
{
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, int.Parse(port));
// Create a TCP/IP socket.    
Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
StateObject stateObject = new StateObject();
stateObject.num = num;
stateObject.workSocket = socketClient;
 
// Connect to the remote endpoint.    
socketClient.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), stateObject);
 
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
 
private void ConnectCallback(IAsyncResult ar)
{
try
{
StateObject stateObject = (StateObject)ar.AsyncState;
// Retrieve the socket from the state object.    
//Socket client = (Socket)ar.AsyncState;
// Complete the connection.    
stateObject.workSocket.EndConnect(ar);
ShowStatus("已连接服务器。。。。\r\n");
stateObject.workSocket.BeginReceive(stateObject.buffer, 0, stateObject.buffer.Length, 0, new AsyncCallback(ReadCallback), stateObject);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

运行示例如图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值